Bug #10522

SSL_VERSION not handled properly in Net::Http, OpenSSL libraries

Added by dresselm (Matt Dressel) over 4 years ago. Updated over 2 years ago.

Target version:
ruby -v:
ruby 2.1.3p242


While using the Faraday gem with the default net/http adapter, we are passing an explicit ssl_version to net/http, however we still received handshake warnings from the server suggesting that the ssl_version was not getting down to the OpenSSL layer. After realizing that the Typhoeus adapter works just fine, I decided to dig deeper into Net::Http.

The Net::Http#connect method passes the ssl_version to OpenSSL::SSL::SSLContext via the set_params method. This appears to be problematic. The only case I can get to work as expected calls ssl_version= without calling set_params at all. I believe the error revolves around the set_params calling setters for all params (always includes an ssl_version).


Updated by dresselm (Matt Dressel) over 4 years ago

This has become quite a problem due to POODLE and the systematic phasing out of SSLv3 support from many of the APIs we use in production.

We use the following abstracted gems that sit atop net/http & openssl:

  • RestClient
  • Typhoeus

Both suffer the same handshake problems. If this is actually not a problem and I am misdiagnosing it, let me know how it should work and I will update the documentation / tests.

Updated by dresselm (Matt Dressel) over 4 years ago

Who is the best person to review this? AKA who should I assign this to?

Updated by shugo (Shugo Maeda) over 4 years ago

  • Status changed from Open to Feedback

Matt Dressel wrote:

What exception is raised?

The following code works fine on my box (x86_64-linux):

  def test_allow_tls_v1_for_client
    # server does not support SSLv2 / SSLv3
    ctx_proc = { |ctx| ctx.options = OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv3 | OpenSSL::SSL::OP_NO_SSLv2 }
    start_server_version(:TLSv1_1, ctx_proc) { |server, port|
      ctx =
      # It appears that explicitly calling 'ssl_version=' directly
      # is required rather than allowing `set_params` to call it via `__send__`
      ctx.set_params(ssl_version: :TLSv1_1, # soils the ssl_version
                     verify_mode: OpenSSL::SSL::VERIFY_NONE)
      assert_nothing_raised(*HANDSHAKE_ERRORS) { server_connect(port, ctx) { |ssl| } }

I had to add verify_mode: to bypass certificate verification.

Updated by zzak (Zachary Scott) over 4 years ago

  • Assignee set to openssl
  • Priority changed from 5 to Normal

Updated by rhenium (Kazuki Yamaguchi) over 2 years ago

  • Status changed from Feedback to Rejected

As commented at the GitHub PR, there doesn't seem to be anything wrong. ssl_socket.set_params(ssl_version: :TLSv1) should be equivalent to ssl_socket.set_params; ssl_socket.ssl_version = :TLSv1.

Also available in: Atom PDF