summaryrefslogtreecommitdiff
path: root/jni/ruby/lib/rubygems/security/trust_dir.rb
diff options
context:
space:
mode:
authorJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-16 18:49:26 +0900
committerJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-30 00:39:06 +0900
commitfcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch)
tree64cb17de3f41a2b6fef2368028fbd00349946994 /jni/ruby/lib/rubygems/security/trust_dir.rb
Fresh start
Diffstat (limited to 'jni/ruby/lib/rubygems/security/trust_dir.rb')
-rw-r--r--jni/ruby/lib/rubygems/security/trust_dir.rb118
1 files changed, 118 insertions, 0 deletions
diff --git a/jni/ruby/lib/rubygems/security/trust_dir.rb b/jni/ruby/lib/rubygems/security/trust_dir.rb
new file mode 100644
index 0000000..76ef89a
--- /dev/null
+++ b/jni/ruby/lib/rubygems/security/trust_dir.rb
@@ -0,0 +1,118 @@
+##
+# 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,
+ }
+
+ ##
+ # 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::DIGEST_ALGORITHM
+ 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
+
+ open destination, 'wb', @permissions[:trusted_cert] do |io|
+ io.write certificate.to_pem
+ 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
+ if File.exist? @dir then
+ 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
+