1class Gem::Security::TrustDir 2 3 DEFAULT_PERMISSIONS = { 4 :trust_dir => 0700, 5 :trusted_cert => 0600, 6 } 7 8 def initialize dir, permissions = DEFAULT_PERMISSIONS 9 @dir = dir 10 @permissions = permissions 11 12 @digester = Gem::Security::DIGEST_ALGORITHM 13 end 14 15 attr_reader :dir 16 17 ## 18 # Returns the path to the trusted +certificate+ 19 20 def cert_path certificate 21 name_path certificate.subject 22 end 23 24 ## 25 # Enumerates trusted certificates. 26 27 def each_certificate 28 return enum_for __method__ unless block_given? 29 30 glob = File.join @dir, '*.pem' 31 32 Dir[glob].each do |certificate_file| 33 begin 34 certificate = load_certificate certificate_file 35 36 yield certificate, certificate_file 37 rescue OpenSSL::X509::CertificateError 38 next # HACK warn 39 end 40 end 41 end 42 43 ## 44 # Returns the issuer certificate of the given +certificate+ if it exists in 45 # the trust directory. 46 47 def issuer_of certificate 48 path = name_path certificate.issuer 49 50 return unless File.exist? path 51 52 load_certificate path 53 end 54 55 ## 56 # Returns the path to the trusted certificate with the given ASN.1 +name+ 57 58 def name_path name 59 digest = @digester.hexdigest name.to_s 60 61 File.join @dir, "cert-#{digest}.pem" 62 end 63 64 ## 65 # Loads the given +certificate_file+ 66 67 def load_certificate certificate_file 68 pem = File.read certificate_file 69 70 OpenSSL::X509::Certificate.new pem 71 end 72 73 ## 74 # Add a certificate to trusted certificate list. 75 76 def trust_cert certificate 77 verify 78 79 destination = cert_path certificate 80 81 open destination, 'wb', @permissions[:trusted_cert] do |io| 82 io.write certificate.to_pem 83 end 84 end 85 86 ## 87 # Make sure the trust directory exists. If it does exist, make sure it's 88 # actually a directory. If not, then create it with the appropriate 89 # permissions. 90 91 def verify 92 if File.exist? @dir then 93 raise Gem::Security::Exception, 94 "trust directory #{@dir} is not a directory" unless 95 File.directory? @dir 96 97 FileUtils.chmod 0700, @dir 98 else 99 FileUtils.mkdir_p @dir, :mode => @permissions[:trust_dir] 100 end 101 end 102 103end 104 105