Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/install-rubygems.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
strategy:
matrix:
ruby: [ 2.3.8, 2.4.10, 2.5.8, 2.6.6, 2.7.1, jruby-9.2.11.1 ]
openssl: [true, false]
steps:
- uses: actions/checkout@v2
- name: Setup ruby
Expand All @@ -25,6 +26,11 @@ jobs:
run: ruby -Ilib -S rake install 2> errors.txt
- name: Check rubygems install produced no warnings
run: test ! -s errors.txt || (cat errors.txt && exit 1)
- name: Simulate no openssl
run: ruby util/remove_openssl.rb
if: matrix.openssl == false
- name: Run installed rubygems
run: gem list bundler
- name: Run bundler installed as a default gem
run: bundle --version
- name: Check bundler man pages were installed and are properly picked up
Expand Down
1 change: 1 addition & 0 deletions Manifest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ lib/rubygems/installer_uninstaller_utils.rb
lib/rubygems/local_remote_options.rb
lib/rubygems/mock_gem_ui.rb
lib/rubygems/name_tuple.rb
lib/rubygems/openssl.rb
lib/rubygems/package.rb
lib/rubygems/package/digest_io.rb
lib/rubygems/package/file_source.rb
Expand Down
7 changes: 0 additions & 7 deletions bundler/lib/bundler/vendored_persistent.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
# frozen_string_literal: true

# We forcibly require OpenSSL, because net/http/persistent will only autoload
# it. On some Rubies, autoload fails but explicit require succeeds.
begin
require "openssl"
rescue LoadError
# some Ruby builds don't have OpenSSL
end
module Bundler
module Persistent
module Net
Expand Down
5 changes: 0 additions & 5 deletions bundler/spec/support/artifice/fail.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
# frozen_string_literal: true

require "net/http"
begin
require "net/https"
rescue LoadError
nil # net/https or openssl
end

# We can't use artifice here because it uses rack

Expand Down
6 changes: 0 additions & 6 deletions lib/rubygems/commands/cert_command.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
# frozen_string_literal: true
require 'rubygems/command'
require 'rubygems/security'
begin
require 'openssl'
rescue LoadError => e
raise unless (e.respond_to?(:path) && e.path == 'openssl') ||
e.message =~ / -- openssl$/
end

class Gem::Commands::CertCommand < Gem::Command
def initialize
Expand Down
7 changes: 7 additions & 0 deletions lib/rubygems/openssl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

begin
require "openssl"
rescue LoadError => e
raise unless e.path == 'openssl'
end
8 changes: 1 addition & 7 deletions lib/rubygems/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def self.get_cert_files
end

def self.configure_connection_for_https(connection, cert_files)
require 'net/https'
require 'openssl'
connection.use_ssl = true
connection.verify_mode =
Gem.configuration.ssl_verify_mode || OpenSSL::SSL::VERIFY_PEER
Expand Down Expand Up @@ -77,12 +77,6 @@ def self.configure_connection_for_https(connection, cert_files)
end

connection
rescue LoadError => e
raise unless (e.respond_to?(:path) && e.path == 'openssl') ||
e.message =~ / -- openssl$/

raise Gem::Exception.new(
'Unable to require openssl, install OpenSSL and rebuild Ruby (preferred) or use non-HTTPS sources')
end

def self.verify_certificate(store_context)
Expand Down
2 changes: 1 addition & 1 deletion lib/rubygems/s3_uri_signer.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require 'base64'
require 'digest'
require 'openssl'
require 'rubygems/openssl'

##
# S3URISigner implements AWS SigV4 for S3 Source to avoid a dependency on the aws-sdk-* gems
Expand Down
8 changes: 1 addition & 7 deletions lib/rubygems/security.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,7 @@

require 'rubygems/exceptions'
require 'fileutils'

begin
require 'openssl'
rescue LoadError => e
raise unless (e.respond_to?(:path) && e.path == 'openssl') ||
e.message =~ / -- openssl$/
end
require_relative 'openssl'

##
# = Signing gems
Expand Down
2 changes: 0 additions & 2 deletions lib/rubygems/security/policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ class Gem::Security::Policy
# options.

def initialize(name, policy = {}, opt = {})
require 'openssl'

@name = name

@opt = opt
Expand Down
4 changes: 2 additions & 2 deletions lib/rubygems/specification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2407,7 +2407,7 @@ def test_files # :nodoc:
# still have their default values are omitted.

def to_ruby
require 'openssl'
require_relative 'openssl'
mark_version
result = []
result << "# -*- encoding: utf-8 -*-"
Expand Down Expand Up @@ -2447,7 +2447,7 @@ def to_ruby
next if handled.include? attr_name
current_value = self.send(attr_name)
if current_value != default_value(attr_name) || self.class.required_attribute?(attr_name)
result << " s.#{attr_name} = #{ruby_code current_value}" unless current_value.is_a?(OpenSSL::PKey::RSA)
result << " s.#{attr_name} = #{ruby_code current_value}" unless defined?(OpenSSL::PKey::RSA) && current_value.is_a?(OpenSSL::PKey::RSA)
end
end

Expand Down
80 changes: 42 additions & 38 deletions test/rubygems/test_bundled_ca.rb
Original file line number Diff line number Diff line change
@@ -1,57 +1,61 @@
# frozen_string_literal: true
require 'rubygems/test_case'
require 'net/https'
require 'net/http'
require 'rubygems/openssl'

unless defined?(OpenSSL::SSL)
warn 'Skipping bundled certificates tests. openssl not found.'
end

require 'rubygems/request'

# = Testing Bundled CA
#
# The tested hosts are explained in detail here: https://github.com/rubygems/rubygems/commit/5e16a5428f973667cabfa07e94ff939e7a83ebd9
#

if ENV["CI"] || ENV["TEST_SSL"]
class TestBundledCA < Gem::TestCase
THIS_FILE = File.expand_path __FILE__

def bundled_certificate_store
store = OpenSSL::X509::Store.new
class TestBundledCA < Gem::TestCase
THIS_FILE = File.expand_path __FILE__

ssl_cert_glob =
File.expand_path '../../../lib/rubygems/ssl_certs/*/*.pem', THIS_FILE
def bundled_certificate_store
store = OpenSSL::X509::Store.new

Dir[ssl_cert_glob].each do |ssl_cert|
store.add_file ssl_cert
end
ssl_cert_glob =
File.expand_path '../../../lib/rubygems/ssl_certs/*/*.pem', THIS_FILE

store
Dir[ssl_cert_glob].each do |ssl_cert|
store.add_file ssl_cert
end

def assert_https(host)
self.assertions += 1
http = Net::HTTP.new(host, 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.cert_store = bundled_certificate_store
http.get('/')
rescue Errno::ENOENT, Errno::ETIMEDOUT, SocketError
skip "#{host} seems offline, I can't tell whether ssl would work."
rescue OpenSSL::SSL::SSLError => e
# Only fail for certificate verification errors
if e.message =~ /certificate verify failed/
flunk "#{host} is not verifiable using the included certificates. Error was: #{e.message}"
end
raise
end
store
end

def test_accessing_rubygems
assert_https('rubygems.org')
def assert_https(host)
self.assertions += 1
http = Net::HTTP.new(host, 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.cert_store = bundled_certificate_store
http.get('/')
rescue Errno::ENOENT, Errno::ETIMEDOUT, SocketError
skip "#{host} seems offline, I can't tell whether ssl would work."
rescue OpenSSL::SSL::SSLError => e
# Only fail for certificate verification errors
if e.message =~ /certificate verify failed/
flunk "#{host} is not verifiable using the included certificates. Error was: #{e.message}"
end
raise
end

def test_accessing_fastly
assert_https('rubygems.global.ssl.fastly.net')
end
def test_accessing_rubygems
assert_https('rubygems.org')
end

def test_accessing_new_index
assert_https('fastly.rubygems.org')
end
def test_accessing_fastly
assert_https('rubygems.global.ssl.fastly.net')
end
end

def test_accessing_new_index
assert_https('fastly.rubygems.org')
end
end if defined?(OpenSSL::SSL)
2 changes: 2 additions & 0 deletions test/rubygems/test_gem_dependency_installer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,8 @@ def test_install_platform_is_ignored_when_a_file_is_specified
assert_equal %w[a-1-cpu-other_platform-1], inst.installed_gems.map {|s| s.full_name }
end

require 'rubygems/openssl'

if defined? OpenSSL
def test_install_security_policy
util_setup_gems
Expand Down
9 changes: 3 additions & 6 deletions test/rubygems/test_gem_package.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,12 @@ def test_add_checksums
'SHA512' => {
'metadata.gz' => metadata_sha512,
'data.tar.gz' => Digest::SHA512.hexdigest(tar),
}
}

if defined?(OpenSSL::Digest)
expected['SHA256'] = {
},
'SHA256' => {
'metadata.gz' => metadata_sha256,
'data.tar.gz' => Digest::SHA256.hexdigest(tar),
}
end
}

assert_equal expected, YAML.load(checksums)
end
Expand Down
2 changes: 1 addition & 1 deletion test/rubygems/test_gem_remote_fetcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
end

unless defined?(OpenSSL::SSL)
warn 'Skipping Gem::Request tests. openssl not found.'
warn 'Skipping Gem::RemoteFetcher tests. openssl not found.'
end

require 'rubygems/remote_fetcher'
Expand Down
3 changes: 3 additions & 0 deletions test/rubygems/test_gem_specification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2431,6 +2431,9 @@ def test_to_ruby
end

def test_to_ruby_with_rsa_key
require 'rubygems/openssl'
skip 'openssl is missing' unless defined?(OpenSSL::PKey::RSA)

rsa_key = OpenSSL::PKey::RSA.new(2048)
@a2.signing_key = rsa_key
ruby_code = @a2.to_ruby
Expand Down
55 changes: 55 additions & 0 deletions util/remove_openssl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true

require "rbconfig"
require "fileutils"

class OpensslSimulator
attr_reader :openssl_rb, :openssl_gemspec, :openssl_ext

def initialize
archdir = RbConfig::CONFIG["archdir"]
rubylibdir = RbConfig::CONFIG["rubylibdir"]
default_specifications_dir = Gem.default_specifications_dir

@openssl_rb = File.join(rubylibdir, "openssl.rb")
@openssl_gemspec = Dir.glob("#{default_specifications_dir}/openssl-*.gemspec").first

@openssl_ext = if RUBY_PLATFORM == "java"
File.join(rubylibdir, "jopenssl.jar")
else
File.join(archdir, "openssl.so")
end
end

def hide_openssl
hide_file openssl_rb
hide_file openssl_ext
hide_file openssl_gemspec if openssl_gemspec
end

def unhide_openssl
unhide_file openssl_gemspec if openssl_gemspec
unhide_file openssl_ext
unhide_file openssl_rb
end

private

def hide_file(file)
FileUtils.mv file, file + "_"
end

def unhide_file(file)
FileUtils.mv file + "_", file
end
end

if $0 == __FILE__
openssl_simulate = OpensslSimulator.new

if ARGV[0] == "--revert"
openssl_simulate.unhide_openssl
else
openssl_simulate.hide_openssl
end
end