mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
118 lines
2.5 KiB
Ruby
118 lines
2.5 KiB
Ruby
# frozen_string_literal: true
|
|
##
|
|
# The TrustDir manages the trusted certificates for gem signature
|
|
# verification.
|
|
|
|
class Gem::Security::TrustDir
|
|
##
|
|
# Default permissions for the trust directory and its contents
|
|
|
|
DEFAULT_PERMISSIONS = {
|
|
:trust_dir => 0700,
|
|
:trusted_cert => 0600,
|
|
}.freeze
|
|
|
|
##
|
|
# The directory where trusted certificates will be stored.
|
|
|
|
attr_reader :dir
|
|
|
|
##
|
|
# Creates a new TrustDir using +dir+ where the directory and file
|
|
# permissions will be checked according to +permissions+
|
|
|
|
def initialize(dir, permissions = DEFAULT_PERMISSIONS)
|
|
@dir = dir
|
|
@permissions = permissions
|
|
|
|
@digester = Gem::Security.create_digest
|
|
end
|
|
|
|
##
|
|
# Returns the path to the trusted +certificate+
|
|
|
|
def cert_path(certificate)
|
|
name_path certificate.subject
|
|
end
|
|
|
|
##
|
|
# Enumerates trusted certificates.
|
|
|
|
def each_certificate
|
|
return enum_for __method__ unless block_given?
|
|
|
|
glob = File.join @dir, '*.pem'
|
|
|
|
Dir[glob].each do |certificate_file|
|
|
begin
|
|
certificate = load_certificate certificate_file
|
|
|
|
yield certificate, certificate_file
|
|
rescue OpenSSL::X509::CertificateError
|
|
next # HACK warn
|
|
end
|
|
end
|
|
end
|
|
|
|
##
|
|
# Returns the issuer certificate of the given +certificate+ if it exists in
|
|
# the trust directory.
|
|
|
|
def issuer_of(certificate)
|
|
path = name_path certificate.issuer
|
|
|
|
return unless File.exist? path
|
|
|
|
load_certificate path
|
|
end
|
|
|
|
##
|
|
# Returns the path to the trusted certificate with the given ASN.1 +name+
|
|
|
|
def name_path(name)
|
|
digest = @digester.hexdigest name.to_s
|
|
|
|
File.join @dir, "cert-#{digest}.pem"
|
|
end
|
|
|
|
##
|
|
# Loads the given +certificate_file+
|
|
|
|
def load_certificate(certificate_file)
|
|
pem = File.read certificate_file
|
|
|
|
OpenSSL::X509::Certificate.new pem
|
|
end
|
|
|
|
##
|
|
# Add a certificate to trusted certificate list.
|
|
|
|
def trust_cert(certificate)
|
|
verify
|
|
|
|
destination = cert_path certificate
|
|
|
|
File.open destination, 'wb', 0600 do |io|
|
|
io.write certificate.to_pem
|
|
io.chmod(@permissions[:trusted_cert])
|
|
end
|
|
end
|
|
|
|
##
|
|
# Make sure the trust directory exists. If it does exist, make sure it's
|
|
# actually a directory. If not, then create it with the appropriate
|
|
# permissions.
|
|
|
|
def verify
|
|
require 'fileutils'
|
|
if File.exist? @dir
|
|
raise Gem::Security::Exception,
|
|
"trust directory #{@dir} is not a directory" unless
|
|
File.directory? @dir
|
|
|
|
FileUtils.chmod 0700, @dir
|
|
else
|
|
FileUtils.mkdir_p @dir, :mode => @permissions[:trust_dir]
|
|
end
|
|
end
|
|
end
|