diff --git a/.gitignore b/.gitignore index ec3ec3c50..557a08f97 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,7 @@ __debug_bin # Ignore generated binaries bin/vagrant-go* + +# extension +tmp* +lib/vagrant/vagrant_ssl.so diff --git a/Rakefile b/Rakefile index 2af398a1e..34ce6386e 100644 --- a/Rakefile +++ b/Rakefile @@ -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 diff --git a/ext/vagrant_ssl/extconf.rb b/ext/vagrant_ssl/extconf.rb new file mode 100644 index 000000000..44b307d1b --- /dev/null +++ b/ext/vagrant_ssl/extconf.rb @@ -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 diff --git a/ext/vagrant_ssl/vagrant_ssl.c b/ext/vagrant_ssl/vagrant_ssl.c new file mode 100644 index 000000000..4c65c26e1 --- /dev/null +++ b/ext/vagrant_ssl/vagrant_ssl.c @@ -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 diff --git a/ext/vagrant_ssl/vagrant_ssl.h b/ext/vagrant_ssl/vagrant_ssl.h new file mode 100644 index 000000000..4f9eccf14 --- /dev/null +++ b/ext/vagrant_ssl/vagrant_ssl.h @@ -0,0 +1,14 @@ +#if !defined(_VAGRANT_SSL_H_) +#define _VAGRANT_SSL_H_ + +#include +#if OPENSSL_VERSION_NUMBER >= (3 << 28) +#define _VAGRANT_SSL_PROVIDER_ + +#include +#include +#endif + +void Init_vagrant_ssl(void); + +#endif diff --git a/lib/vagrant.rb b/lib/vagrant.rb index 0aa58a582..78adf49b2 100644 --- a/lib/vagrant.rb +++ b/lib/vagrant.rb @@ -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" diff --git a/vagrant.gemspec b/vagrant.gemspec index eb595a41e..2a740089a 100644 --- a/vagrant.gemspec +++ b/vagrant.gemspec @@ -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