class HTTPX::SSL

  1. lib/httpx/io/ssl.rb
  2. lib/httpx/plugins/proxy/ssh.rb
  3. show all
Superclass: TCP

Constants

TLS_OPTIONS = tls_options.freeze  

Attributes

Public Class methods

new(_, _, options)
[show source]
   # File lib/httpx/io/ssl.rb
17 def initialize(_, _, options)
18   super
19 
20   @ssl_session = @session_new_cb = nil
21 
22   ctx_options = TLS_OPTIONS
23   ctx_options = ctx_options.merge(options.ssl) if options.ssl && !options.ssl.empty?
24   @sni_hostname = (ctx_options.delete(:hostname) if ctx_options.key?(:hostname)) || @hostname
25 
26   if @keep_open && @io.is_a?(OpenSSL::SSL::SSLSocket)
27     # externally initiated ssl socket
28     @ctx = @io.context
29     @state = :negotiated
30   else
31     @ctx = OpenSSL::SSL::SSLContext.new
32     @ctx.set_params(ctx_options)
33     unless @ctx.session_cache_mode.nil? # a dummy method on JRuby
34       @ctx.session_cache_mode =
35         OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT | OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
36     end
37     init_session_new_cb
38 
39     yield(self) if block_given?
40   end
41 
42   @verify_hostname = @ctx.verify_hostname
43 end

Public Instance methods

can_verify_peer?()
[show source]
   # File lib/httpx/io/ssl.rb
84 def can_verify_peer?
85   @ctx.verify_mode == OpenSSL::SSL::VERIFY_PEER
86 end
connect()
[show source]
    # File lib/httpx/io/ssl.rb
106 def connect
107   return if @state == :negotiated
108 
109   unless @state == :connected
110     super
111     return unless @state == :connected
112   end
113 
114   # @type ivar @io: OpenSSL::SSL::SSLSocket
115 
116   unless @io.is_a?(OpenSSL::SSL::SSLSocket)
117     if (hostname_is_ip = (@ip == @sni_hostname)) && @ctx.verify_hostname
118       # IPv6 address would be "[::1]", must turn to "0000:0000:0000:0000:0000:0000:0000:0001" for cert SAN check
119       @sni_hostname = @ip.to_string
120       # IP addresses in SNI is not valid per RFC 6066, section 3.
121       @ctx.verify_hostname = false
122     end
123 
124     ssl = OpenSSL::SSL::SSLSocket.new(@io, @ctx)
125 
126     ssl.hostname = @sni_hostname unless hostname_is_ip
127     ssl.session = @ssl_session unless ssl_session_expired?
128     ssl.sync_close = true
129 
130     @io = ssl
131   end
132   try_ssl_connect
133 end
connected?()
[show source]
   # File lib/httpx/io/ssl.rb
96 def connected?
97   @state == :negotiated
98 end
protocol()
[show source]
   # File lib/httpx/io/ssl.rb
64 def protocol
65   return super unless @io.is_a?(OpenSSL::SSL::SSLSocket)
66 
67   @io.alpn_protocol || super
68 end
session_new_cb(&pr)

sets the ssl session callback to be picked up by the ssl context.

[show source]
   # File lib/httpx/io/ssl.rb
47 def session_new_cb(&pr)
48   @session_new_cb = pr
49 end
ssl_session_expired?()
[show source]
    # File lib/httpx/io/ssl.rb
100 def ssl_session_expired?
101   ssl_session = @ssl_session
102 
103   ssl_session.nil? || Process.clock_gettime(Process::CLOCK_REALTIME) >= (ssl_session.time.to_f + ssl_session.timeout)
104 end
try_ssl_connect()
[show source]
    # File lib/httpx/io/ssl.rb
135 def try_ssl_connect
136   # @type ivar @io: OpenSSL::SSL::SSLSocket
137   ret = @io.connect_nonblock(exception: false)
138   log(level: 3, color: :cyan) { "TLS CONNECT: #{ret}..." }
139   case ret
140   when :wait_readable
141     @interests = :r
142     return
143   when :wait_writable
144     @interests = :w
145     return
146   end
147   @io.post_connection_check(@sni_hostname) if @ctx.verify_mode != OpenSSL::SSL::VERIFY_NONE && @verify_hostname
148   transition(:negotiated)
149   @interests = :w
150 end
verify_hostname(host)
[show source]
   # File lib/httpx/io/ssl.rb
88 def verify_hostname(host)
89   return false if @ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE
90   # @type ivar @io: OpenSSL::SSL::SSLSocket
91   return false if !@io.respond_to?(:peer_cert) || (peer_cert = @io.peer_cert).nil?
92 
93   OpenSSL::SSL.verify_certificate_identity(peer_cert, host)
94 end