ruby / openssl

Provides SSL, TLS and general purpose cryptography.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How do I set the OpenSSL::SSL::OP_IGNORE_UNEXPECTED_EOF flag?

QWYNG opened this issue · comments

Hi Thank you for great gem.

Since I started using ruby 3.1.4, I have been getting the error SSL_read: unexpected eof while reading.
I decided to ignore it and used OpenSSL::SSL::OP_IGNORE_UNEXPECTED_EOF as follows.

Module.new do
  def options
    super | OpenSSL::SSL::OP_IGNORE_UNEXPECTED_EOF
  end

  OpenSSL::SSL::SSLContext.prepend(self)
end

I thought this would set the OP_IGNORE_UNEXPECTED_EOF flag at any point, but I continue to get errors.
How do I set the OpenSSL::SSL::OP_IGNORE_UNEXPECTED_EOF flag correctly?

Environment

irb(main):002:0> RUBY_VERSION
=> "3.1.4"
irb(main):003:0> OpenSSL::OPENSSL_VERSION
=> "OpenSSL 3.0.2 15 Mar 2022"
irb(main):004:0> OpenSSL::OPENSSL_LIBRARY_VERSION
=> "OpenSSL 3.0.2 15 Mar 2022"
irb(main):005:0>

ps
The gem I use for http communication is httpclient, and ruby/openssl is used as follows

https://github.com/nahi/httpclient/blob/4658227a46f7caa633ef8036f073bbd1f0a955a2/lib/httpclient/ssl_socket.rb#L132-L143C8

I logged it and the flag seemed to be set.

Module.new do
  def gets(_)
    super
  rescue OpenSSL::SSL::SSLError => e
    if e.message == 'SSL_read: unexpected eof while reading'
      Rails.logger.warn("unexpected eof while reading. ssl_socket.context.option: #{@ssl_socket.context.options}")
    end
    raise e
  end

  HTTPClient::SSLSocket.prepend(self)
end
unexpected eof while reading. ssl_socket.context.option: 2181169360

[1] pry(main)> 2181169360 & OpenSSL::SSL::OP_IGNORE_UNEXPECTED_EOF
=> 128

ref: https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_options.html

OpenSSL:SSL::SSLContext#options is purely a getter method wrapping SSL_CTX_get_options(). This is not used by ruby/openssl itself, hence it doesn't work. You need to call OpenSSL:SSL::SSLContext#options= (which wraps SSL_CTX_set_options()) to actually set the option.

If I were to override the default behavior globally, I would monkey patch OpenSSL:SSL::SSLContext#initialize and/or #set_params.

Note that it's probably a bad idea, though. The OpenSSL::SSL::OP_IGNORE_UNEXPECTED_EOF option can potentially open it to a TLS truncation attack, and should only be used when the upper protocol layers can prevent it by other means.

@rhenium Thank you!

Note that it's probably a bad idea, though. The OpenSSL::SSL::OP_IGNORE_UNEXPECTED_EOF option can potentially open it to a TLS truncation attack, and should only be used when the upper protocol layers can prevent it by other means.

Exactly. We'll come up with a fundamental solution as well.