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
8 changes: 3 additions & 5 deletions resources/ssl/README-SSL.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ Addition of certificate to the Ruby default CA list
----------------------------------------------

Additional certificates shall be stored in `<install-path>/ssl/certs/<yourfile>.pem` in pem format.
This directory is checked by the builtin openssl gem for certificate verification.
When the openssl gem is installed via source gem, then the directory `<msys2-dir>\<mingwarch>\etc\ssl\certs` is used instead.
Each pem file may contain several certificates.
The pem files must be activated for CA lookup by using a OpenSSL-hashed filename.
There is a helper script in `<install-path>/ssl/certs/c_rehash.rb` to generate these hash files.
There is a helper script in `<install-path>/ssl/certs/c_rehash.rb` to generate these hash files in both directories and in the `ca-bundle.crt` described below.
Just double click `c_rehash.rb` to activate all pem files in the directory.

Addition of certificates to the Devkit/MSYS2 CA list
Expand All @@ -41,7 +43,3 @@ MSYS2 has its own CA list which is maintained by [the MSYS2 project](http://msys
This CA list is used by all MSYS2 tools like pacman, wget or curl.
In order to add an additional CA certificate for MSYS2, you have to append it to `<msys2-dir>\usr\ssl\certs\ca-bundle.crt` in PEM format.
In a default Rubyinstaller-Devkit-2.5-x64 setup this file is here: `c:\Ruby25-x64\msys64\usr\ssl\certs\ca-bundle.crt`

Please also note, that pacman's builtin HTTP client doesn't work well with proxies.
You probably have to enable `wget` in `<msys2-dir>\etc\pacman.conf`.
It also respects `http_proxy` and `https_proxy` environment variables set in Windows system settings.
67 changes: 58 additions & 9 deletions resources/ssl/c_rehash.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#!/usr/bin/env ruby

# This is a helper script to add trusted CA certificates to RubyInstaller.
# See README-SSL.md for more details.

require 'openssl'

class CHashDir
Expand Down Expand Up @@ -74,12 +77,34 @@ def crl_filename(crl)

def do_hash_dir
Dir.chdir(@dirpath) do
delete_symlink
delete_symlink(".")

begin
msys = RubyInstaller::Runtime.msys2_installation
mingw_certs = File.expand_path("../etc/ssl/certs", msys.mingw_bin_path)
msys_bundle = File.expand_path("usr/ssl/certs/ca-bundle.crt", msys.msys_path)
rescue RubyInstaller::Runtime::Msys2Installation::MsysNotFound
else
delete_symlink(mingw_certs)
delete_from_bundle(msys_bundle)
end

Dir.glob('*.pem') do |pemfile|
load_pem_file(pemfile).each do |cert|
case cert
when OpenSSL::X509::Certificate
link_hash_cert(cert)
# Create hash file in rubyinstallers's ssl directory
# This is used by builtin openssl.gem
link_hash_cert(cert, ".")

# Create hash file in msys2/mingw's ssl directory
# This is used when openssl.gem is built from sources
link_hash_cert(cert, mingw_certs) if mingw_certs

# Create hash file in msys2/mingw's ssl directory
# This is used by MSYS2 tools like curl and pacman
add_to_bundle(cert, msys_bundle) if msys_bundle

when OpenSSL::X509::CRL
link_hash_crl(cert)
else
Expand All @@ -90,19 +115,43 @@ def do_hash_dir
end
end

def delete_symlink
Dir.entries(".").each do |entry|
def delete_symlink(hashdir)
Dir.entries(hashdir).each do |entry|
next unless /^[\da-f]+\.r{0,1}\d+$/ =~ entry
File.unlink(entry) if FileTest.symlink?(entry) or FileTest.file?(entry)
epath = File.join(hashdir, entry)
File.unlink(epath) if FileTest.symlink?(epath) or FileTest.file?(epath)
end
end

def link_hash_cert(cert)
def delete_from_bundle(bundle_fname)
fc = File.read(bundle_fname)

# Create a bak file before modification
fname_bak = bundle_fname + ".bak-ruby"
File.write(fname_bak, fc) unless File.exist?(fname_bak)

# Remove all certs inserted by RubyInstaller
fc = fc.gsub(/# RubyInstaller: [^\n]*\n-----BEGIN CERTIFICATE-----[^-]*-----END CERTIFICATE-----\n*/m, "")
File.write(bundle_fname, fc)
end

def add_to_bundle(cert, bundle_fname)
fc = File.read(bundle_fname)
ct = <<~EOT
# RubyInstaller: #{cert.subject}
#{cert.to_pem}
EOT
fc = ct + fc
File.write(bundle_fname, fc)
STDOUT.puts("#{cert.subject} => #{bundle_fname}") unless @silent
end

def link_hash_cert(cert, hashdir)
name_hash = hash_name(cert.subject)
fingerprint = fingerprint(cert.to_der)
filepath = link_hash(cert, name_hash, fingerprint) { |idx|
"#{name_hash}.#{idx}"
}
filepath = link_hash(cert, name_hash, fingerprint) do |idx|
File.join(hashdir, "#{name_hash}.#{idx}")
end
unless filepath
unless @silent
STDERR.puts("WARNING: Skipping duplicate certificate #{cert.subject}")
Expand Down
Loading