A Gem::Security::Policy object encapsulates the settings for verifying signed gem files. This is the base class. You can either declare an instance of this or use one of the preset security policies in Gem::Security::Policies.
Create a new Gem::Security::Policy object with the given mode and options.
 
               # File rubygems/security/policy.rb, line 27
def initialize(name, policy = {}, opt = {})
  require 'openssl'
  @name = name
  @opt = opt
  # Default to security
  @only_signed   = true
  @only_trusted  = true
  @verify_chain  = true
  @verify_data   = true
  @verify_root   = true
  @verify_signer = true
  policy.each_pair do |key, val|
    case key
    when :verify_data   then @verify_data   = val
    when :verify_signer then @verify_signer = val
    when :verify_chain  then @verify_chain  = val
    when :verify_root   then @verify_root   = val
    when :only_trusted  then @only_trusted  = val
    when :only_signed   then @only_signed   = val
    end
  end
end
             
            Ensures that signer is valid for time and was
signed by the issuer. If the issuer is
nil no verification is performed.
 
               # File rubygems/security/policy.rb, line 88
def check_cert(signer, issuer, time)
  raise Gem::Security::Exception, 'missing signing certificate' unless
    signer
  message = "certificate #{signer.subject}"
  if not_before = signer.not_before and not_before > time
    raise Gem::Security::Exception,
          "#{message} not valid before #{not_before}"
  end
  if not_after = signer.not_after and not_after < time
    raise Gem::Security::Exception, "#{message} not valid after #{not_after}"
  end
  if issuer and not signer.verify issuer.public_key
    raise Gem::Security::Exception,
          "#{message} was not issued by #{issuer.subject}"
  end
  true
end
             
            Verifies each certificate in chain has signed the following
certificate and is valid for the given time.
 
               # File rubygems/security/policy.rb, line 58
def check_chain(chain, time)
  raise Gem::Security::Exception, 'missing signing chain' unless chain
  raise Gem::Security::Exception, 'empty signing chain' if chain.empty?
  begin
    chain.each_cons 2 do |issuer, cert|
      check_cert cert, issuer, time
    end
    true
  rescue Gem::Security::Exception => e
    raise Gem::Security::Exception, "invalid signing chain: #{e.message}"
  end
end
             
            Verifies that data matches the signature created
by public_key and the digest algorithm.
 
               # File rubygems/security/policy.rb, line 77
def check_data(public_key, digest, signature, data)
  raise Gem::Security::Exception, "invalid signature" unless
    public_key.verify digest.new, signature, data.digest
  true
end
             
            Ensures the public key of key matches the public key in
signer
 
               # File rubygems/security/policy.rb, line 114
def check_key(signer, key)
  unless signer and key
    return true unless @only_signed
    raise Gem::Security::Exception, 'missing key or signature'
  end
  raise Gem::Security::Exception,
    "certificate #{signer.subject} does not match the signing key" unless
      signer.public_key.to_pem == key.public_key.to_pem
  true
end
             
            Ensures the root certificate in chain is self-signed and valid
for time.
 
               # File rubygems/security/policy.rb, line 132
def check_root(chain, time)
  raise Gem::Security::Exception, 'missing signing chain' unless chain
  root = chain.first
  raise Gem::Security::Exception, 'missing root certificate' unless root
  raise Gem::Security::Exception,
        "root certificate #{root.subject} is not self-signed " +
        "(issuer #{root.issuer})" if
    root.issuer.to_s != root.subject.to_s # HACK to_s is for ruby 1.8
  check_cert root, root, time
end
             
            Ensures the root of chain has a trusted certificate in
trust_dir and the digests of the two certificates match
according to digester
 
               # File rubygems/security/policy.rb, line 151
def check_trust(chain, digester, trust_dir)
  raise Gem::Security::Exception, 'missing signing chain' unless chain
  root = chain.first
  raise Gem::Security::Exception, 'missing root certificate' unless root
  path = Gem::Security.trust_dir.cert_path root
  unless File.exist? path
    message = "root cert #{root.subject} is not trusted".dup
    message << " (root of signing cert #{chain.last.subject})" if
      chain.length > 1
    raise Gem::Security::Exception, message
  end
  save_cert = OpenSSL::X509::Certificate.new File.read path
  save_dgst = digester.digest save_cert.public_key.to_s
  pkey_str = root.public_key.to_s
  cert_dgst = digester.digest pkey_str
  raise Gem::Security::Exception,
        "trusted root certificate #{root.subject} checksum " +
        "does not match signing root certificate checksum" unless
    save_dgst == cert_dgst
  true
end
             
            For full_name, verifies the certificate chain is
valid, the digests match the signatures
signatures created by the signer depending on the
policy settings.
If key is given it is used to validate the signing
certificate.
 
               # File rubygems/security/policy.rb, line 211
def verify(chain, key = nil, digests = {}, signatures = {},
           full_name = '(unknown)')
  if signatures.empty?
    if @only_signed
      raise Gem::Security::Exception,
        "unsigned gems are not allowed by the #{name} policy"
    elsif digests.empty?
      # lack of signatures is irrelevant if there is nothing to check
      # against
    else
      alert_warning "#{full_name} is not signed"
      return
    end
  end
  opt       = @opt
  digester  = Gem::Security::DIGEST_ALGORITHM
  trust_dir = opt[:trust_dir]
  time      = Time.now
  _, signer_digests = digests.find do |algorithm, file_digests|
    file_digests.values.first.name == Gem::Security::DIGEST_NAME
  end
  if @verify_data
    raise Gem::Security::Exception, 'no digests provided (probable bug)' if
      signer_digests.nil? or signer_digests.empty?
  else
    signer_digests = {}
  end
  signer = chain.last
  check_key signer, key if key
  check_cert signer, nil, time if @verify_signer
  check_chain chain, time if @verify_chain
  check_root chain, time if @verify_root
  if @only_trusted
    check_trust chain, digester, trust_dir
  elsif signatures.empty? and digests.empty?
    # trust is irrelevant if there's no signatures to verify
  else
    alert_warning "#{subject signer} is not trusted for #{full_name}"
  end
  signatures.each do |file, _|
    digest = signer_digests[file]
    raise Gem::Security::Exception, "missing digest for #{file}" unless
      digest
  end
  signer_digests.each do |file, digest|
    signature = signatures[file]
    raise Gem::Security::Exception, "missing signature for #{file}" unless
      signature
    check_data signer.public_key, digester, signature, digest if @verify_data
  end
  true
end
             
            Extracts the certificate chain from the spec and calls verify to ensure the signatures and
certificate chain is valid according to the policy..
 
               # File rubygems/security/policy.rb, line 283
def verify_signatures(spec, digests, signatures)
  chain = spec.cert_chain.map do |cert_pem|
    OpenSSL::X509::Certificate.new cert_pem
  end
  verify chain, nil, digests, signatures, spec.full_name
  true
end