Can no longer pass file contents as ca_file property with OpenSSL 3
thoiberg opened this issue · comments
Hi, I have some code that was retrieving the string contents of a certificate from a database (so "-----BEGIN CERTIFICATE..."
) and setting it to the ca_file
property with OpenSSL. This works for OpenSSL 1.1.1, but on OpenSSL 3.0.9 raises SSL_CTX_load_verify_file: system lib (OpenSSL::SSL::SSLError)
. From what I've read I'm guessing this might have always been unsupported behaviour with OpenSSL 1.1.1, but I was wondering if this was an intentional breaking change, or if there is an alternative way to pass the contents of a certificate to OpenSSL.
I have a set of minimal reproduction steps based of the wget sample below:
OpenSSL 1.1.1
docker run -it ruby:3.1-bullseye
require 'net/https'
pem_contents = File.read(OpenSSL::X509::DEFAULT_CERT_FILE)
uri = URI.parse("https://github.com/ruby/openssl")
h = Net::HTTP.new(uri.host, uri.port)
h.use_ssl = true
h.ca_file = pem_contents
path = uri.path.empty? ? "/" : uri.path
h.get2(path)
# returns <Net::HTTPOK 200 OK readbody=true>
OpenSSL 3.0.9
docker run -it ruby:3.1-bookworm
require 'net/https'
pem_contents = File.read(OpenSSL::X509::DEFAULT_CERT_FILE)
uri = URI.parse("https://github.com/ruby/openssl")
h = Net::HTTP.new(uri.host, uri.port)
h.use_ssl = true
h.ca_file = pem_contents
path = uri.path.empty? ? "/" : uri.path
h.get2(path)
# raises SSL_CTX_load_verify_file: system lib (OpenSSL::SSL::SSLError)
full stacktrace
/usr/local/lib/ruby/3.1.0/net/http.rb:1081:in `initialize': SSL_CTX_load_verify_file: system lib (OpenSSL::SSL::SSLError)
from /usr/local/lib/ruby/3.1.0/net/http.rb:1081:in `new'
from /usr/local/lib/ruby/3.1.0/net/http.rb:1081:in `connect'
from /usr/local/lib/ruby/3.1.0/net/http.rb:995:in `do_start'
from /usr/local/lib/ruby/3.1.0/net/http.rb:984:in `start'
from /usr/local/lib/ruby/3.1.0/net/http.rb:1564:in `request'
from /usr/local/lib/ruby/3.1.0/net/http.rb:1474:in `request_get'
from (irb):10:in `<main>'
from /usr/local/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
from /usr/local/bin/irb:25:in `load'
from /usr/local/bin/irb:25:in `<main>'
Yes, Net::HTTP#ca_file (OpenSSL::SSL::SSLContext#ca_file) wants the path to the file.
I don't think setting the file contents to the attribute ever worked. With OpenSSL 1.1.1, it is simply ignored with a verbose-mode warning:
openssl/ext/openssl/ossl_ssl.c
Lines 882 to 892 in 97fb410
$ ruby -w -ropenssl -e'ctx=OpenSSL::SSL::SSLContext.new; ctx.ca_file=File.read("/etc/ssl/certs/Go_Daddy_Class_2_CA.pem"); ctx.setup'
-e:1: warning: can't set verify locations
The behavior difference was not intentional, but I think the OpenSSL <= 1.1.1 code should've also raised an exception since this is clearly an error case.
ahhhhhh, ok that makes a lot more sense 😄 . Thanks for investigating 🙇
Reopening because the OpenSSL <= 1.1.1 code should be fixed.