1# frozen_string_literal: false
2=begin
3= Info
4  'OpenSSL for Ruby 2' project
5  Copyright (C) 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
6  All rights reserved.
7
8= Licence
9  This program is licensed under the same licence as Ruby.
10  (See the file 'LICENCE'.)
11=end
12
13require "openssl/buffering"
14require "io/nonblock"
15require "ipaddr"
16
17module OpenSSL
18  module SSL
19    class SSLContext
20      DEFAULT_PARAMS = { # :nodoc:
21        :min_version => OpenSSL::SSL::TLS1_VERSION,
22        :verify_mode => OpenSSL::SSL::VERIFY_PEER,
23        :verify_hostname => true,
24        :options => -> {
25          opts = OpenSSL::SSL::OP_ALL
26          opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS
27          opts |= OpenSSL::SSL::OP_NO_COMPRESSION
28          opts
29        }.call
30      }
31
32      if defined?(OpenSSL::PKey::DH)
33        DEFAULT_2048 = OpenSSL::PKey::DH.new <<-_end_of_pem_
34-----BEGIN DH PARAMETERS-----
35MIIBCAKCAQEA7E6kBrYiyvmKAMzQ7i8WvwVk9Y/+f8S7sCTN712KkK3cqd1jhJDY
36JbrYeNV3kUIKhPxWHhObHKpD1R84UpL+s2b55+iMd6GmL7OYmNIT/FccKhTcveab
37VBmZT86BZKYyf45hUF9FOuUM9xPzuK3Vd8oJQvfYMCd7LPC0taAEljQLR4Edf8E6
38YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
391bNveX5wInh5GDx1FGhKBZ+s1H+aedudCm7sCgRwv8lKWYGiHzObSma8A86KG+MD
407Lo5JquQ3DlBodj3IDyPrxIv96lvRPFtAwIBAg==
41-----END DH PARAMETERS-----
42        _end_of_pem_
43        private_constant :DEFAULT_2048
44
45        DEFAULT_TMP_DH_CALLBACK = lambda { |ctx, is_export, keylen| # :nodoc:
46          warn "using default DH parameters." if $VERBOSE
47          DEFAULT_2048
48        }
49      end
50
51      if !(OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL") &&
52           OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10100000)
53        DEFAULT_PARAMS.merge!(
54          ciphers: %w{
55            ECDHE-ECDSA-AES128-GCM-SHA256
56            ECDHE-RSA-AES128-GCM-SHA256
57            ECDHE-ECDSA-AES256-GCM-SHA384
58            ECDHE-RSA-AES256-GCM-SHA384
59            DHE-RSA-AES128-GCM-SHA256
60            DHE-DSS-AES128-GCM-SHA256
61            DHE-RSA-AES256-GCM-SHA384
62            DHE-DSS-AES256-GCM-SHA384
63            ECDHE-ECDSA-AES128-SHA256
64            ECDHE-RSA-AES128-SHA256
65            ECDHE-ECDSA-AES128-SHA
66            ECDHE-RSA-AES128-SHA
67            ECDHE-ECDSA-AES256-SHA384
68            ECDHE-RSA-AES256-SHA384
69            ECDHE-ECDSA-AES256-SHA
70            ECDHE-RSA-AES256-SHA
71            DHE-RSA-AES128-SHA256
72            DHE-RSA-AES256-SHA256
73            DHE-RSA-AES128-SHA
74            DHE-RSA-AES256-SHA
75            DHE-DSS-AES128-SHA256
76            DHE-DSS-AES256-SHA256
77            DHE-DSS-AES128-SHA
78            DHE-DSS-AES256-SHA
79            AES128-GCM-SHA256
80            AES256-GCM-SHA384
81            AES128-SHA256
82            AES256-SHA256
83            AES128-SHA
84            AES256-SHA
85          }.join(":"),
86        )
87      end
88
89      DEFAULT_CERT_STORE = OpenSSL::X509::Store.new # :nodoc:
90      DEFAULT_CERT_STORE.set_default_paths
91      DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
92
93      # A callback invoked when DH parameters are required.
94      #
95      # The callback is invoked with the Session for the key exchange, an
96      # flag indicating the use of an export cipher and the keylength
97      # required.
98      #
99      # The callback must return an OpenSSL::PKey::DH instance of the correct
100      # key length.
101
102      attr_accessor :tmp_dh_callback
103
104      # A callback invoked at connect time to distinguish between multiple
105      # server names.
106      #
107      # The callback is invoked with an SSLSocket and a server name.  The
108      # callback must return an SSLContext for the server name or nil.
109      attr_accessor :servername_cb
110
111      # call-seq:
112      #    SSLContext.new           -> ctx
113      #    SSLContext.new(:TLSv1)   -> ctx
114      #    SSLContext.new("SSLv23") -> ctx
115      #
116      # Creates a new SSL context.
117      #
118      # If an argument is given, #ssl_version= is called with the value. Note
119      # that this form is deprecated. New applications should use #min_version=
120      # and #max_version= as necessary.
121      def initialize(version = nil)
122        self.options |= OpenSSL::SSL::OP_ALL
123        self.ssl_version = version if version
124      end
125
126      ##
127      # call-seq:
128      #   ctx.set_params(params = {}) -> params
129      #
130      # Sets saner defaults optimized for the use with HTTP-like protocols.
131      #
132      # If a Hash _params_ is given, the parameters are overridden with it.
133      # The keys in _params_ must be assignment methods on SSLContext.
134      #
135      # If the verify_mode is not VERIFY_NONE and ca_file, ca_path and
136      # cert_store are not set then the system default certificate store is
137      # used.
138      def set_params(params={})
139        params = DEFAULT_PARAMS.merge(params)
140        self.options = params.delete(:options) # set before min_version/max_version
141        params.each{|name, value| self.__send__("#{name}=", value) }
142        if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
143          unless self.ca_file or self.ca_path or self.cert_store
144            self.cert_store = DEFAULT_CERT_STORE
145          end
146        end
147        return params
148      end
149
150      # call-seq:
151      #    ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION
152      #    ctx.min_version = :TLS1_2
153      #    ctx.min_version = nil
154      #
155      # Sets the lower bound on the supported SSL/TLS protocol version. The
156      # version may be specified by an integer constant named
157      # OpenSSL::SSL::*_VERSION, a Symbol, or +nil+ which means "any version".
158      #
159      # Be careful that you don't overwrite OpenSSL::SSL::OP_NO_{SSL,TLS}v*
160      # options by #options= once you have called #min_version= or
161      # #max_version=.
162      #
163      # === Example
164      #   ctx = OpenSSL::SSL::SSLContext.new
165      #   ctx.min_version = OpenSSL::SSL::TLS1_1_VERSION
166      #   ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
167      #
168      #   sock = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx)
169      #   sock.connect # Initiates a connection using either TLS 1.1 or TLS 1.2
170      def min_version=(version)
171        set_minmax_proto_version(version, @max_proto_version ||= nil)
172        @min_proto_version = version
173      end
174
175      # call-seq:
176      #    ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
177      #    ctx.max_version = :TLS1_2
178      #    ctx.max_version = nil
179      #
180      # Sets the upper bound of the supported SSL/TLS protocol version. See
181      # #min_version= for the possible values.
182      def max_version=(version)
183        set_minmax_proto_version(@min_proto_version ||= nil, version)
184        @max_proto_version = version
185      end
186
187      # call-seq:
188      #    ctx.ssl_version = :TLSv1
189      #    ctx.ssl_version = "SSLv23"
190      #
191      # Sets the SSL/TLS protocol version for the context. This forces
192      # connections to use only the specified protocol version. This is
193      # deprecated and only provided for backwards compatibility. Use
194      # #min_version= and #max_version= instead.
195      #
196      # === History
197      # As the name hints, this used to call the SSL_CTX_set_ssl_version()
198      # function which sets the SSL method used for connections created from
199      # the context. As of Ruby/OpenSSL 2.1, this accessor method is
200      # implemented to call #min_version= and #max_version= instead.
201      def ssl_version=(meth)
202        meth = meth.to_s if meth.is_a?(Symbol)
203        if /(?<type>_client|_server)\z/ =~ meth
204          meth = $`
205          if $VERBOSE
206            warn "#{caller(1, 1)[0]}: method type #{type.inspect} is ignored"
207          end
208        end
209        version = METHODS_MAP[meth.intern] or
210          raise ArgumentError, "unknown SSL method `%s'" % meth
211        set_minmax_proto_version(version, version)
212        @min_proto_version = @max_proto_version = version
213      end
214
215      METHODS_MAP = {
216        SSLv23: 0,
217        SSLv2: OpenSSL::SSL::SSL2_VERSION,
218        SSLv3: OpenSSL::SSL::SSL3_VERSION,
219        TLSv1: OpenSSL::SSL::TLS1_VERSION,
220        TLSv1_1: OpenSSL::SSL::TLS1_1_VERSION,
221        TLSv1_2: OpenSSL::SSL::TLS1_2_VERSION,
222      }.freeze
223      private_constant :METHODS_MAP
224
225      # The list of available SSL/TLS methods. This constant is only provided
226      # for backwards compatibility.
227      METHODS = METHODS_MAP.flat_map { |name,|
228        [name, :"#{name}_client", :"#{name}_server"]
229      }.freeze
230      deprecate_constant :METHODS
231    end
232
233    module SocketForwarder
234      def addr
235        to_io.addr
236      end
237
238      def peeraddr
239        to_io.peeraddr
240      end
241
242      def setsockopt(level, optname, optval)
243        to_io.setsockopt(level, optname, optval)
244      end
245
246      def getsockopt(level, optname)
247        to_io.getsockopt(level, optname)
248      end
249
250      def fcntl(*args)
251        to_io.fcntl(*args)
252      end
253
254      def closed?
255        to_io.closed?
256      end
257
258      def do_not_reverse_lookup=(flag)
259        to_io.do_not_reverse_lookup = flag
260      end
261    end
262
263    def verify_certificate_identity(cert, hostname)
264      should_verify_common_name = true
265      cert.extensions.each{|ext|
266        next if ext.oid != "subjectAltName"
267        ostr = OpenSSL::ASN1.decode(ext.to_der).value.last
268        sequence = OpenSSL::ASN1.decode(ostr.value)
269        sequence.value.each{|san|
270          case san.tag
271          when 2 # dNSName in GeneralName (RFC5280)
272            should_verify_common_name = false
273            return true if verify_hostname(hostname, san.value)
274          when 7 # iPAddress in GeneralName (RFC5280)
275            should_verify_common_name = false
276            if san.value.size == 4 || san.value.size == 16
277              begin
278                return true if san.value == IPAddr.new(hostname).hton
279              rescue IPAddr::InvalidAddressError
280              end
281            end
282          end
283        }
284      }
285      if should_verify_common_name
286        cert.subject.to_a.each{|oid, value|
287          if oid == "CN"
288            return true if verify_hostname(hostname, value)
289          end
290        }
291      end
292      return false
293    end
294    module_function :verify_certificate_identity
295
296    def verify_hostname(hostname, san) # :nodoc:
297      # RFC 5280, IA5String is limited to the set of ASCII characters
298      return false unless san.ascii_only?
299      return false unless hostname.ascii_only?
300
301      # See RFC 6125, section 6.4.1
302      # Matching is case-insensitive.
303      san_parts = san.downcase.split(".")
304
305      # TODO: this behavior should probably be more strict
306      return san == hostname if san_parts.size < 2
307
308      # Matching is case-insensitive.
309      host_parts = hostname.downcase.split(".")
310
311      # RFC 6125, section 6.4.3, subitem 2.
312      # If the wildcard character is the only character of the left-most
313      # label in the presented identifier, the client SHOULD NOT compare
314      # against anything but the left-most label of the reference
315      # identifier (e.g., *.example.com would match foo.example.com but
316      # not bar.foo.example.com or example.com).
317      return false unless san_parts.size == host_parts.size
318
319      # RFC 6125, section 6.4.3, subitem 1.
320      # The client SHOULD NOT attempt to match a presented identifier in
321      # which the wildcard character comprises a label other than the
322      # left-most label (e.g., do not match bar.*.example.net).
323      return false unless verify_wildcard(host_parts.shift, san_parts.shift)
324
325      san_parts.join(".") == host_parts.join(".")
326    end
327    module_function :verify_hostname
328
329    def verify_wildcard(domain_component, san_component) # :nodoc:
330      parts = san_component.split("*", -1)
331
332      return false if parts.size > 2
333      return san_component == domain_component if parts.size == 1
334
335      # RFC 6125, section 6.4.3, subitem 3.
336      # The client SHOULD NOT attempt to match a presented identifier
337      # where the wildcard character is embedded within an A-label or
338      # U-label of an internationalized domain name.
339      return false if domain_component.start_with?("xn--") && san_component != "*"
340
341      parts[0].length + parts[1].length < domain_component.length &&
342      domain_component.start_with?(parts[0]) &&
343      domain_component.end_with?(parts[1])
344    end
345    module_function :verify_wildcard
346
347    class SSLSocket
348      include Buffering
349      include SocketForwarder
350
351      attr_reader :hostname
352
353      # The underlying IO object.
354      attr_reader :io
355      alias :to_io :io
356
357      # The SSLContext object used in this connection.
358      attr_reader :context
359
360      # Whether to close the underlying socket as well, when the SSL/TLS
361      # connection is shut down. This defaults to +false+.
362      attr_accessor :sync_close
363
364      # call-seq:
365      #    ssl.sysclose => nil
366      #
367      # Sends "close notify" to the peer and tries to shut down the SSL
368      # connection gracefully.
369      #
370      # If sync_close is set to +true+, the underlying IO is also closed.
371      def sysclose
372        return if closed?
373        stop
374        io.close if sync_close
375      end
376
377      # call-seq:
378      #   ssl.post_connection_check(hostname) -> true
379      #
380      # Perform hostname verification following RFC 6125.
381      #
382      # This method MUST be called after calling #connect to ensure that the
383      # hostname of a remote peer has been verified.
384      def post_connection_check(hostname)
385        if peer_cert.nil?
386          msg = "Peer verification enabled, but no certificate received."
387          if using_anon_cipher?
388            msg += " Anonymous cipher suite #{cipher[0]} was negotiated. " \
389                   "Anonymous suites must be disabled to use peer verification."
390          end
391          raise SSLError, msg
392        end
393
394        unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
395          raise SSLError, "hostname \"#{hostname}\" does not match the server certificate"
396        end
397        return true
398      end
399
400      # call-seq:
401      #   ssl.session -> aSession
402      #
403      # Returns the SSLSession object currently used, or nil if the session is
404      # not established.
405      def session
406        SSL::Session.new(self)
407      rescue SSL::Session::SessionError
408        nil
409      end
410
411      private
412
413      def using_anon_cipher?
414        ctx = OpenSSL::SSL::SSLContext.new
415        ctx.ciphers = "aNULL"
416        ctx.ciphers.include?(cipher)
417      end
418
419      def client_cert_cb
420        @context.client_cert_cb
421      end
422
423      def tmp_dh_callback
424        @context.tmp_dh_callback || OpenSSL::SSL::SSLContext::DEFAULT_TMP_DH_CALLBACK
425      end
426
427      def tmp_ecdh_callback
428        @context.tmp_ecdh_callback
429      end
430
431      def session_new_cb
432        @context.session_new_cb
433      end
434
435      def session_get_cb
436        @context.session_get_cb
437      end
438    end
439
440    ##
441    # SSLServer represents a TCP/IP server socket with Secure Sockets Layer.
442    class SSLServer
443      include SocketForwarder
444      # When true then #accept works exactly the same as TCPServer#accept
445      attr_accessor :start_immediately
446
447      # Creates a new instance of SSLServer.
448      # * _srv_ is an instance of TCPServer.
449      # * _ctx_ is an instance of OpenSSL::SSL::SSLContext.
450      def initialize(svr, ctx)
451        @svr = svr
452        @ctx = ctx
453        unless ctx.session_id_context
454          # see #6137 - session id may not exceed 32 bytes
455          prng = ::Random.new($0.hash)
456          session_id = prng.bytes(16).unpack('H*')[0]
457          @ctx.session_id_context = session_id
458        end
459        @start_immediately = true
460      end
461
462      # Returns the TCPServer passed to the SSLServer when initialized.
463      def to_io
464        @svr
465      end
466
467      # See TCPServer#listen for details.
468      def listen(backlog=5)
469        @svr.listen(backlog)
470      end
471
472      # See BasicSocket#shutdown for details.
473      def shutdown(how=Socket::SHUT_RDWR)
474        @svr.shutdown(how)
475      end
476
477      # Works similar to TCPServer#accept.
478      def accept
479        # Socket#accept returns [socket, addrinfo].
480        # TCPServer#accept returns a socket.
481        # The following comma strips addrinfo.
482        sock, = @svr.accept
483        begin
484          ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
485          ssl.sync_close = true
486          ssl.accept if @start_immediately
487          ssl
488        rescue Exception => ex
489          if ssl
490            ssl.close
491          else
492            sock.close
493          end
494          raise ex
495        end
496      end
497
498      # See IO#close for details.
499      def close
500        @svr.close
501      end
502    end
503  end
504end
505