From 873bac15ae7ddb3032114fb61587314840444ba3 Mon Sep 17 00:00:00 2001 From: Will Jordan Date: Thu, 16 Feb 2017 10:52:04 -0800 Subject: [PATCH 1/3] Enable compact index when OpenSSL FIPS mode is enabled but not active --- lib/bundler/fetcher/compact_index.rb | 16 ++++++-- spec/bundler/fetcher/compact_index_spec.rb | 44 +++++++++++++++++++--- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/lib/bundler/fetcher/compact_index.rb b/lib/bundler/fetcher/compact_index.rb index dcc9d57c134..896f69592e0 100644 --- a/lib/bundler/fetcher/compact_index.rb +++ b/lib/bundler/fetcher/compact_index.rb @@ -122,14 +122,24 @@ def call(path, headers) end def md5_available? + return true unless fips_enabled? && Process.respond_to?(:fork) + pid = fork do + $stderr.reopen(File.new("/dev/null", "w")) + require "digest/md5" + Digest::MD5.new + exit + end + Process.wait pid + $?.success? + end + + def fips_enabled? begin require "openssl" - return false if defined?(OpenSSL::OPENSSL_FIPS) && OpenSSL::OPENSSL_FIPS rescue LoadError nil end - - true + defined?(OpenSSL::OPENSSL_FIPS) && OpenSSL::OPENSSL_FIPS end end end diff --git a/spec/bundler/fetcher/compact_index_spec.rb b/spec/bundler/fetcher/compact_index_spec.rb index 5e85f906ba1..7888dbf1bd4 100644 --- a/spec/bundler/fetcher/compact_index_spec.rb +++ b/spec/bundler/fetcher/compact_index_spec.rb @@ -3,8 +3,8 @@ RSpec.describe Bundler::Fetcher::CompactIndex do let(:downloader) { double(:downloader) } - let(:remote) { double(:remote, :cache_slug => "lsjdf") } let(:display_uri) { URI("http://sampleuri.com") } + let(:remote) { double(:remote, :cache_slug => "lsjdf", :uri => display_uri) } let(:compact_index) { described_class.new(downloader, remote, display_uri) } before do @@ -26,16 +26,48 @@ end describe "#available?" do - context "when OpenSSL is in FIPS mode", :ruby => ">= 2.0.0" do + before do + allow(compact_index).to receive(:compact_index_client). + and_return(double(:compact_index_client, :update_and_parse_checksums! => true)) + end + + it "returns true" do + expect(compact_index).to be_available + end + + it "does not fork" do + expect(compact_index).to receive(:fork).never + compact_index.available? + end + + context "when OpenSSL is FIPS-enabled", :ruby => ">= 2.0.0" do before { stub_const("OpenSSL::OPENSSL_FIPS", true) } - it "returns false" do - expect(compact_index).to_not be_available + context "when FIPS-mode is active" do + before do + allow(Digest::MD5).to receive(:new) do + # OpenSSL writes to STDERR and kills the current process with SIGABRT + # when FIPS mode prevents MD5 from being used. + $stderr.write "Digest MD5 forbidden in FIPS mode!" + Process.kill("ABRT", Process.pid) + end + end + + it "returns false" do + expect(compact_index).to_not be_available + end + + it "outputs nothing to stderr" do + expect { compact_index.available? }.to_not output.to_stderr_from_any_process + end end - it "never requires digest/md5" do - expect(Kernel).to receive(:require).with("digest/md5").never + it "returns true" do + expect(compact_index).to be_available + end + it "does fork" do + expect(compact_index).to receive(:fork).and_call_original compact_index.available? end end From 9c389ff678dee6f4801845a1c82884d31b3499be Mon Sep 17 00:00:00 2001 From: Will Jordan Date: Fri, 17 Feb 2017 07:16:58 -0800 Subject: [PATCH 2/3] simplify `md5_available?` test using `OpenSSL::Digest:MD5.digest` --- lib/bundler/fetcher/compact_index.rb | 25 ++++++---------------- spec/bundler/fetcher/compact_index_spec.rb | 22 +++++++++---------- 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/lib/bundler/fetcher/compact_index.rb b/lib/bundler/fetcher/compact_index.rb index 896f69592e0..97de88101bd 100644 --- a/lib/bundler/fetcher/compact_index.rb +++ b/lib/bundler/fetcher/compact_index.rb @@ -122,24 +122,13 @@ def call(path, headers) end def md5_available? - return true unless fips_enabled? && Process.respond_to?(:fork) - pid = fork do - $stderr.reopen(File.new("/dev/null", "w")) - require "digest/md5" - Digest::MD5.new - exit - end - Process.wait pid - $?.success? - end - - def fips_enabled? - begin - require "openssl" - rescue LoadError - nil - end - defined?(OpenSSL::OPENSSL_FIPS) && OpenSSL::OPENSSL_FIPS + require "openssl" + OpenSSL::Digest::MD5.digest("") + true + rescue LoadError + true + rescue OpenSSL::Digest::DigestError + false end end end diff --git a/spec/bundler/fetcher/compact_index_spec.rb b/spec/bundler/fetcher/compact_index_spec.rb index 7888dbf1bd4..b0a23cd5a55 100644 --- a/spec/bundler/fetcher/compact_index_spec.rb +++ b/spec/bundler/fetcher/compact_index_spec.rb @@ -35,9 +35,14 @@ expect(compact_index).to be_available end - it "does not fork" do - expect(compact_index).to receive(:fork).never - compact_index.available? + context "when OpenSSL is not available" do + before do + allow(compact_index).to receive(:require).with("openssl").and_raise(LoadError) + end + + it "returns true" do + expect(compact_index).to be_available + end end context "when OpenSSL is FIPS-enabled", :ruby => ">= 2.0.0" do @@ -45,6 +50,8 @@ context "when FIPS-mode is active" do before do + allow(OpenSSL::Digest::MD5).to receive(:digest). + and_raise(OpenSSL::Digest::DigestError) allow(Digest::MD5).to receive(:new) do # OpenSSL writes to STDERR and kills the current process with SIGABRT # when FIPS mode prevents MD5 from being used. @@ -56,20 +63,11 @@ it "returns false" do expect(compact_index).to_not be_available end - - it "outputs nothing to stderr" do - expect { compact_index.available? }.to_not output.to_stderr_from_any_process - end end it "returns true" do expect(compact_index).to be_available end - - it "does fork" do - expect(compact_index).to receive(:fork).and_call_original - compact_index.available? - end end end From 21b3358d66b2748cc92a41b9d91d5f844fffc64f Mon Sep 17 00:00:00 2001 From: Will Jordan Date: Fri, 17 Feb 2017 07:53:30 -0800 Subject: [PATCH 3/3] remove unused Process.kill mock in FIPS-mode spec --- spec/bundler/fetcher/compact_index_spec.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/spec/bundler/fetcher/compact_index_spec.rb b/spec/bundler/fetcher/compact_index_spec.rb index b0a23cd5a55..e653c1ea43b 100644 --- a/spec/bundler/fetcher/compact_index_spec.rb +++ b/spec/bundler/fetcher/compact_index_spec.rb @@ -52,12 +52,6 @@ before do allow(OpenSSL::Digest::MD5).to receive(:digest). and_raise(OpenSSL::Digest::DigestError) - allow(Digest::MD5).to receive(:new) do - # OpenSSL writes to STDERR and kills the current process with SIGABRT - # when FIPS mode prevents MD5 from being used. - $stderr.write "Digest MD5 forbidden in FIPS mode!" - Process.kill("ABRT", Process.pid) - end end it "returns false" do