/usr/share/doc/ruby1.8-examples/examples/openssl/c_rehash.rb is in ruby1.8-examples 1.8.7.352-2ubuntu1.6.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | #!/usr/bin/ruby1.8
require 'openssl'
require 'digest/md5'
class CHashDir
include Enumerable
def initialize(dirpath)
@dirpath = dirpath
@fingerprint_cache = @cert_cache = @crl_cache = nil
end
def hash_dir(silent = false)
# ToDo: Should lock the directory...
@silent = silent
@fingerprint_cache = Hash.new
@cert_cache = Hash.new
@crl_cache = Hash.new
do_hash_dir
end
def get_certs(name = nil)
if name
@cert_cache[hash_name(name)]
else
@cert_cache.values.flatten
end
end
def get_crls(name = nil)
if name
@crl_cache[hash_name(name)]
else
@crl_cache.values.flatten
end
end
def delete_crl(crl)
File.unlink(crl_filename(crl))
hash_dir(true)
end
def add_crl(crl)
File.open(crl_filename(crl), "w") do |f|
f << crl.to_pem
end
hash_dir(true)
end
def load_pem_file(filepath)
str = File.read(filepath)
begin
OpenSSL::X509::Certificate.new(str)
rescue
begin
OpenSSL::X509::CRL.new(str)
rescue
begin
OpenSSL::X509::Request.new(str)
rescue
nil
end
end
end
end
private
def crl_filename(crl)
path(hash_name(crl.issuer)) + '.pem'
end
def do_hash_dir
Dir.chdir(@dirpath) do
delete_symlink
Dir.glob('*.pem') do |pemfile|
cert = load_pem_file(pemfile)
case cert
when OpenSSL::X509::Certificate
link_hash_cert(pemfile, cert)
when OpenSSL::X509::CRL
link_hash_crl(pemfile, cert)
else
STDERR.puts("WARNING: #{pemfile} does not contain a certificate or CRL: skipping") unless @silent
end
end
end
end
def delete_symlink
Dir.entries(".").each do |entry|
next unless /^[\da-f]+\.r{0,1}\d+$/ =~ entry
File.unlink(entry) if FileTest.symlink?(entry)
end
end
def link_hash_cert(org_filename, cert)
name_hash = hash_name(cert.subject)
fingerprint = fingerprint(cert.to_der)
filepath = link_hash(org_filename, name_hash, fingerprint) { |idx|
"#{name_hash}.#{idx}"
}
unless filepath
unless @silent
STDERR.puts("WARNING: Skipping duplicate certificate #{org_filename}")
end
else
(@cert_cache[name_hash] ||= []) << path(filepath)
end
end
def link_hash_crl(org_filename, crl)
name_hash = hash_name(crl.issuer)
fingerprint = fingerprint(crl.to_der)
filepath = link_hash(org_filename, name_hash, fingerprint) { |idx|
"#{name_hash}.r#{idx}"
}
unless filepath
unless @silent
STDERR.puts("WARNING: Skipping duplicate CRL #{org_filename}")
end
else
(@crl_cache[name_hash] ||= []) << path(filepath)
end
end
def link_hash(org_filename, name, fingerprint)
idx = 0
filepath = nil
while true
filepath = yield(idx)
break unless FileTest.symlink?(filepath) or FileTest.exist?(filepath)
if @fingerprint_cache[filepath] == fingerprint
return false
end
idx += 1
end
STDOUT.puts("#{org_filename} => #{filepath}") unless @silent
symlink(org_filename, filepath)
@fingerprint_cache[filepath] = fingerprint
filepath
end
def symlink(from, to)
begin
File.symlink(from, to)
rescue
File.open(to, "w") do |f|
f << File.read(from)
end
end
end
def path(filename)
File.join(@dirpath, filename)
end
def hash_name(name)
sprintf("%x", name.hash)
end
def fingerprint(der)
Digest::MD5.hexdigest(der).upcase
end
end
if $0 == __FILE__
dirlist = ARGV
dirlist << '/usr/ssl/certs' if dirlist.empty?
dirlist.each do |dir|
CHashDir.new(dir).hash_dir
end
end
|