def initialize(io, security_policy = nil)
@io = io
@tarreader = Gem::Package::TarReader.new @io
has_meta = false
data_sig, meta_sig, data_dgst, meta_dgst = nil, nil, nil, nil
dgst_algo = security_policy ? Gem::Security::OPT[:dgst_algo] : nil
@tarreader.each do |entry|
case entry.full_name
when "metadata"
@metadata = load_gemspec entry.read
has_meta = true
when "metadata.gz"
begin
sio = nil
if security_policy
Gem.ensure_ssl_available
sio = StringIO.new(entry.read)
meta_dgst = dgst_algo.digest(sio.string)
sio.rewind
end
args = [sio || entry]
args << { :external_encoding => Encoding::UTF_8 } if
Object.const_defined?(:Encoding)
gzis = Zlib::GzipReader.new(*args)
@metadata = load_gemspec(gzis)
has_meta = true
ensure
gzis.close unless gzis.nil?
end
when 'metadata.gz.sig'
meta_sig = entry.read
when 'data.tar.gz.sig'
data_sig = entry.read
when 'data.tar.gz'
if security_policy
Gem.ensure_ssl_available
data_dgst = dgst_algo.digest(entry.read)
end
end
end
if security_policy then
Gem.ensure_ssl_available
if String === security_policy then
if Gem::Security::Policies.key? security_policy then
security_policy = Gem::Security::Policies[security_policy]
elsif File.exist? security_policy then
security_policy = YAML.load File.read(security_policy)
else
raise Gem::Exception, "Unknown trust policy '#{security_policy}'"
end
end
if data_sig && data_dgst && meta_sig && meta_dgst then
begin
security_policy.verify_gem(data_sig, data_dgst, @metadata.cert_chain)
rescue Exception => e
raise "Couldn't verify data signature: #{e}"
end
begin
security_policy.verify_gem(meta_sig, meta_dgst, @metadata.cert_chain)
rescue Exception => e
raise "Couldn't verify metadata signature: #{e}"
end
elsif security_policy.only_signed
raise Gem::Exception, "Unsigned gem"
else
end
end
@tarreader.rewind
unless has_meta then
path = io.path if io.respond_to? :path
error = Gem::Package::FormatError.new 'no metadata found', path
raise error
end
end