Project

General

Profile

Bug #10533

HTTP reconnection with SNI does not send correct hostname

Added by drbrain (Eric Hodel) over 3 years ago. Updated over 2 years ago.

Status:
Closed
Priority:
Normal
Target version:
-
ruby -v:
ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin14.0]
[ruby-core:66388]

Description

When reconnecting after connection timeout on an SNI connection the server name is not sent during reconnect which results in a failed reconnection:

$ cat test.rb
require 'net/http'
uri = URI 'https://david.shanske.com'

Net::HTTP.start uri.hostname, uri.port, use_ssl: true do |http|
  req = Net::HTTP::Get.new uri
  response = http.request req
  p response.code
  sleep 310
  req = Net::HTTP::Get.new uri
  response = http.request req
  p response.code
end
$ ruby -v test.rb
ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin14.0]
"200"
/usr/local/lib/ruby/2.1.0/openssl/ssl.rb:178:in `post_connection_check': hostname "david.shanske.com" does not match the server certificate (OpenSSL::SSL::SSLError)
        from /usr/local/lib/ruby/2.1.0/net/http.rb:922:in `connect'
        from /usr/local/lib/ruby/2.1.0/net/http.rb:1447:in `begin_transport'
        from /usr/local/lib/ruby/2.1.0/net/http.rb:1404:in `transport_request'
        from /usr/local/lib/ruby/2.1.0/net/http.rb:1378:in `request'
        from test.rb:10:in `block in <main>'
        from /usr/local/lib/ruby/2.1.0/net/http.rb:853:in `start'
        from /usr/local/lib/ruby/2.1.0/net/http.rb:583:in `start'
        from test.rb:4:in `<main>'
net.http.bug10533.patch (685 Bytes) net.http.bug10533.patch only resume valid sessions drbrain (Eric Hodel), 11/21/2014 11:00 PM
net.http.bug10533-2.patch (884 Bytes) net.http.bug10533-2.patch mkarnebeek (Michiel Karnebeek), 06/18/2015 08:35 AM

Related issues

Related to Ruby trunk - Bug #10398: Server Name Indication support broken when reusing a (dead) sessionClosed

Associated revisions

Revision 48563
Added by drbrain (Eric Hodel) about 3 years ago

  • lib/net/http.rb: Do not attempt SSL session resumption when the session is expired. [Bug #10533]

Revision 48563
Added by drbrain (Eric Hodel) about 3 years ago

  • lib/net/http.rb: Do not attempt SSL session resumption when the session is expired. [Bug #10533]

Revision 48563
Added by drbrain (Eric Hodel) about 3 years ago

  • lib/net/http.rb: Do not attempt SSL session resumption when the session is expired. [Bug #10533]

Revision 48563
Added by drbrain (Eric Hodel) about 3 years ago

  • lib/net/http.rb: Do not attempt SSL session resumption when the session is expired. [Bug #10533]

Revision 48636
Added by usa (Usaku NAKAMURA) about 3 years ago

merge revision(s) 48563: [Backport #10533]

* lib/net/http.rb:  Do not attempt SSL session resumption when the
  session is expired.  [Bug #10533]

Revision 49631
Added by nagachika (Tomoyuki Chikanaga) about 3 years ago

merge revision(s) r48563,r46261,r48581: [Backport #10533]

* lib/net/http.rb:  Do not attempt SSL session resumption when the
  session is expired.  [Bug #10533]

History

#1 [ruby-core:66400] Updated by drbrain (Eric Hodel) over 3 years ago

If session resumption is requested with an expired SSL session on an SNI server then the handshake goes wrong and the connection fails as above.

The attached patch only attempts session resumption if the session is still valid.

#2 [ruby-core:66401] Updated by drbrain (Eric Hodel) over 3 years ago

  • Status changed from Open to Assigned
  • Assignee set to naruse (Yui NARUSE)

#3 [ruby-core:66408] Updated by drbrain (Eric Hodel) over 3 years ago

Ultimately I think this may be an OpenSSL bug.

Looking at the ClientHello message for the second connection (which uses session resumption) no ServerNameIndication extension is present. Without this the server won't be able to respond with the correct certificate.

#4 [ruby-core:66453] Updated by drbrain (Eric Hodel) about 3 years ago

  • Assignee changed from naruse (Yui NARUSE) to drbrain (Eric Hodel)

Via #ruby-core IRC:

22:53 nurse: ok > 10533

So I will commit it.

#5 [ruby-core:66454] Updated by drbrain (Eric Hodel) about 3 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

Applied in changeset r48563.


  • lib/net/http.rb: Do not attempt SSL session resumption when the session is expired. [Bug #10533]

#6 [ruby-core:66547] Updated by usa (Usaku NAKAMURA) about 3 years ago

  • Backport changed from 2.0.0: REQUIRED, 2.1: REQUIRED to 2.0.0: DONE, 2.1: REQUIRED

Backported into ruby_2_0_0 at r48636.

#7 [ruby-core:68155] Updated by nagachika (Tomoyuki Chikanaga) about 3 years ago

  • Backport changed from 2.0.0: DONE, 2.1: REQUIRED to 2.0.0: DONE, 2.1: DONE

r48563 and test for it (r46261,r48581) were backported into ruby_2_1 branch at r49631.

#8 [ruby-core:69544] Updated by mkarnebeek (Michiel Karnebeek) over 2 years ago

The patch does not seem to solve the reported issue.

Reconnecting HTTP connections still do not send an SNI.

I'm running ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin14] and checked using Wireshark.

#9 [ruby-core:69631] Updated by mkarnebeek (Michiel Karnebeek) over 2 years ago

Following up on my comment a few days ago:

I ran a test in python using https://github.com/nabla-c0d3/sslyze (with OpenSSL 1.0.2a, same version as in Ruby) and introduced a sleep longer than the ssl session TTL at https://github.com/nabla-c0d3/sslyze/blob/master/plugins/PluginSessionResumption.py#L248 to see if this did supply the SNI

According to Wireshark, this correctly put both the SNI and session ticket in the Client Hello packet.

I think this is evidence that the OpenSSL used is capable of doing this, and that either Net::Http or the c-bindings for ruby to OpenSSL are doing something wrong.

#10 [ruby-core:69648] Updated by mkarnebeek (Michiel Karnebeek) over 2 years ago

It looks like i've solved it: Moving s.hostname = @address before s.session = @ssl_session has solved it on my end.

See the attached patch

#12 [ruby-core:69650] Updated by mkarnebeek (Michiel Karnebeek) over 2 years ago

Root cause seems to be in ossl_ssl.c:

Net::Http calls s.session= (C-method ossl_ssl_set_session), which calls C-method ossl_ssl_setup, which only sets up the ssl client (ssl) once due to "if(!ssl){". The problem is that the hostname setting (the call to SSL_set_tlsext_host_name) is done within that "if(!ssl){" block.

When later Net::Http calls s.connect (C-method ossl_ssl_connect), ossl_ssl_setup is called a second time, but it does not set up the hostname.

#14 Updated by naruse (Yui NARUSE) over 2 years ago

  • Related to Bug #10398: Server Name Indication support broken when reusing a (dead) session added

Also available in: Atom PDF