Add helper for loading OpenSSL providers

On OpenSSL 3, engines have been deprecated being replaced by providers.
The Ruby openssl library supported loading specific engines, but there
is no replacement currently using providers. The winrm communicator
specifically relies on a MD4 which OpenSSL has marked as legacy and no
longer loads by default.

The extension included loads the legacy provider as well as the default
provider. The legacy provider includes MD4, thus allowing winrm to
function again.
This commit is contained in:
Chris Roberts 2023-05-24 15:31:47 -07:00
parent 1b63ba859b
commit 415b006ebd
7 changed files with 84 additions and 0 deletions

4
.gitignore vendored
View File

@ -73,3 +73,7 @@ __debug_bin
# Ignore generated binaries
bin/vagrant-go*
# extension
tmp*
lib/vagrant/vagrant_ssl.so

View File

@ -1,11 +1,16 @@
require 'rubygems'
require 'bundler/setup'
require "rake/extensiontask"
# Immediately sync all stdout so that tools like buildbot can
# immediately load in the output.
$stdout.sync = true
$stderr.sync = true
Rake::ExtensionTask.new "vagrant_ssl" do |ext|
ext.lib_dir = "lib/vagrant"
end
# Load all the rake tasks from the "tasks" folder. This folder
# allows us to nicely separate rake tasks into individual files
# based on their role, which makes development and debugging easier

View File

@ -0,0 +1,11 @@
#!/usr/bin/env ruby
require "mkmf"
if have_header("openssl/opensslv.h")
if ENV["LDFLAGS"]
append_ldflags(ENV["LDFLAGS"].split(" "))
end
append_ldflags(["-lssl"])
create_makefile("vagrant_ssl")
end

View File

@ -0,0 +1,32 @@
#include "vagrant_ssl.h"
#if defined(_VAGRANT_SSL_PROVIDER_)
static VALUE vagrant_ssl_load(VALUE self) {
OSSL_PROVIDER *legacy;
OSSL_PROVIDER *deflt;
legacy = OSSL_PROVIDER_load(NULL, "legacy");
if(legacy == NULL) {
rb_raise(rb_eStandardError, "Failed to load OpenSSL legacy provider");
return self;
}
deflt = OSSL_PROVIDER_load(NULL, "default");
if(deflt == NULL) {
rb_raise(rb_eStandardError, "Failed to load OpenSSL default provider");
return self;
}
}
void Init_vagrant_ssl(void) {
VALUE vagrant;
vagrant = rb_define_module("Vagrant");
rb_define_singleton_method(vagrant, "vagrant_ssl_load", vagrant_ssl_load, 0);
}
#else
void Init_vagrant_ssl(void) {}
#endif

View File

@ -0,0 +1,14 @@
#if !defined(_VAGRANT_SSL_H_)
#define _VAGRANT_SSL_H_
#include <openssl/opensslv.h>
#if OPENSSL_VERSION_NUMBER >= (3 << 28)
#define _VAGRANT_SSL_PROVIDER_
#include <ruby.h>
#include <openssl/provider.h>
#endif
void Init_vagrant_ssl(void);
#endif

View File

@ -121,6 +121,22 @@ ENV.each do |k, v|
global_logger.info("#{k}=#{v.inspect}") if k.start_with?("VAGRANT_")
end
# If the vagrant_ssl library exists, a recent version
# of openssl is in use and its needed to load all the
# providers needed
if File.exist?(File.expand_path("vagrant/vagrant_ssl.so", __dir__))
global_logger.debug("vagrant ssl helper found for loading ssl providers")
begin
require "vagrant/vagrant_ssl"
Vagrant.vagrant_ssl_load
global_logger.debug("ssl providers successfully loaded")
rescue LoadError => err
global_logger.warn("failed to load ssl providers, attempting to continue (#{err})")
rescue => err
global_logger.warn("unexpected failure loading ssl providers, attempting to continue (#{err})")
end
end
# We need these components always so instead of an autoload we
# just require them explicitly here.
require "vagrant/plugin"

View File

@ -49,6 +49,7 @@ Gem::Specification.new do |s|
# Constraint rake to properly handle deprecated method usage
# from within rspec
s.add_development_dependency "rake", "~> 13.0"
s.add_development_dependency "rake-compiler"
s.add_development_dependency "rspec", "~> 3.11"
s.add_development_dependency "rspec-its", "~> 1.3.0"
s.add_development_dependency "fake_ftp", "~> 0.3.0"
@ -104,5 +105,6 @@ Gem::Specification.new do |s|
s.files = unignored_files
s.executables = unignored_files.map { |f| f[/^bin\/(.*)/, 1] }.compact
s.extensions = ["ext/vagrant_ssl/extconf.rb"]
s.require_path = 'lib'
end