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