Class: HTTPX::SSL
Direct Known Subclasses
Constant Summary collapse
- TLS_OPTIONS =
.freeze
Constants included from Loggable
Loggable::COLORS, Loggable::USE_DEBUG_LOG
Instance Attribute Summary collapse
-
#ssl_session ⇒ Object
writeonly
Sets the attribute ssl_session.
Attributes inherited from TCP
#addresses, #interests, #ip, #port, #state
Instance Method Summary collapse
- #can_verify_peer? ⇒ Boolean
- #connect ⇒ Object
- #connected? ⇒ Boolean
-
#init_session_new_cb ⇒ void
sets the ssl context's new session callback, which points at @session_new_cb when available.
-
#initialize(_, _, options) ⇒ SSL
constructor
A new instance of SSL.
-
#protocol ⇒ Object
in jruby, alpn_protocol may return "" https://github.com/jruby/jruby-openssl/issues/287.
-
#session_new_cb {|sess| ... } ⇒ void
session_new_cb not implemented under JRuby.
- #ssl_session_expired? ⇒ Boolean
-
#try_ssl_connect ⇒ void
:nocov:.
- #verify_hostname(host) ⇒ Boolean
Methods inherited from TCP
#add_addresses, #addresses?, #build_socket, #can_disconnect?, #close, #closed?, #do_transition, #inspect, #read, #socket, #to_io, #try_connect, #write
Methods included from Loggable
#log, #log_exception, log_identifiers, #log_redact, #log_redact_body, #log_redact_headers
Constructor Details
#initialize(_, _, options) ⇒ SSL
Returns a new instance of SSL.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/httpx/io/ssl.rb', line 17 def initialize(_, _, ) super @ssl_session = @session_new_cb = nil = TLS_OPTIONS = .merge(.ssl) if .ssl && !.ssl.empty? @sni_hostname = (.delete(:hostname) if .key?(:hostname)) || @hostname if @keep_open && @io.is_a?(OpenSSL::SSL::SSLSocket) # externally initiated ssl socket @ctx = @io.context @state = :negotiated else @ctx = OpenSSL::SSL::SSLContext.new @ctx.set_params() unless @ctx.session_cache_mode.nil? # a dummy method on JRuby @ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT | OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE end init_session_new_cb yield(self) if block_given? end @verify_hostname = @ctx.verify_hostname end |
Instance Attribute Details
#ssl_session=(value) ⇒ Object (writeonly)
Sets the attribute ssl_session
15 16 17 |
# File 'lib/httpx/io/ssl.rb', line 15 def ssl_session=(value) @ssl_session = value end |
Instance Method Details
#can_verify_peer? ⇒ Boolean
84 85 86 |
# File 'lib/httpx/io/ssl.rb', line 84 def can_verify_peer? @ctx.verify_mode == OpenSSL::SSL::VERIFY_PEER end |
#connect ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/httpx/io/ssl.rb', line 106 def connect return if @state == :negotiated unless @state == :connected super return unless @state == :connected end # @type ivar @io: OpenSSL::SSL::SSLSocket unless @io.is_a?(OpenSSL::SSL::SSLSocket) if (hostname_is_ip = (@ip == @sni_hostname)) && @ctx.verify_hostname # IPv6 address would be "[::1]", must turn to "0000:0000:0000:0000:0000:0000:0000:0001" for cert SAN check @sni_hostname = @ip.to_string # IP addresses in SNI is not valid per RFC 6066, section 3. @ctx.verify_hostname = false end ssl = OpenSSL::SSL::SSLSocket.new(@io, @ctx) ssl.hostname = @sni_hostname unless hostname_is_ip ssl.session = @ssl_session unless ssl_session_expired? ssl.sync_close = true @io = ssl end try_ssl_connect end |
#connected? ⇒ Boolean
96 97 98 |
# File 'lib/httpx/io/ssl.rb', line 96 def connected? @state == :negotiated end |
#init_session_new_cb ⇒ void
This method returns an undefined value.
sets the ssl context's new session callback, which points at @session_new_cb when available.
52 53 54 |
# File 'lib/httpx/io/ssl.rb', line 52 def init_session_new_cb @ctx.session_new_cb = proc { |_, sess| @session_new_cb&.call(sess) } end |
#protocol ⇒ Object
in jruby, alpn_protocol may return "" https://github.com/jruby/jruby-openssl/issues/287
73 74 75 76 77 |
# File 'lib/httpx/io/ssl.rb', line 73 def protocol return super unless @io.is_a?(OpenSSL::SSL::SSLSocket) @io.alpn_protocol || super end |
#session_new_cb {|sess| ... } ⇒ void
This method returns an undefined value.
session_new_cb not implemented under JRuby
47 48 49 |
# File 'lib/httpx/io/ssl.rb', line 47 def session_new_cb(&pr) @session_new_cb = pr end |
#ssl_session_expired? ⇒ Boolean
100 101 102 103 104 |
# File 'lib/httpx/io/ssl.rb', line 100 def ssl_session_expired? ssl_session = @ssl_session ssl_session.nil? || Process.clock_gettime(Process::CLOCK_REALTIME) >= (ssl_session.time.to_f + ssl_session.timeout) end |
#try_ssl_connect ⇒ void
This method returns an undefined value.
:nocov:
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'sig/io/ssl.rbs', line 27 def try_ssl_connect # @type ivar @io: OpenSSL::SSL::SSLSocket ret = @io.connect_nonblock(exception: false) log(level: 3, color: :cyan) { "TLS CONNECT: #{ret}..." } case ret when :wait_readable @interests = :r return when :wait_writable @interests = :w return end @io.post_connection_check(@sni_hostname) if @ctx.verify_mode != OpenSSL::SSL::VERIFY_NONE && @verify_hostname transition(:negotiated) @interests = :w end |
#verify_hostname(host) ⇒ Boolean
88 89 90 91 92 93 94 |
# File 'lib/httpx/io/ssl.rb', line 88 def verify_hostname(host) return false if @ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE # @type ivar @io: OpenSSL::SSL::SSLSocket return false if !@io.respond_to?(:peer_cert) || (peer_cert = @io.peer_cert).nil? OpenSSL::SSL.verify_certificate_identity(peer_cert, host) end |