Class: Gem::Security::Policy (Ruby 2.2.2)
Description: Class : Gem::Security::Policy - Ruby 2.2.2

- Home
- Core 2.2.2
- Std-lib 2.2.2
- Downloads

Support for the Ruby 2.2 series has ended. See here for reference.

### Home Classes Methods

### In Files

- rubygems/install_update_options.rb
- rubygems/security/policy.rb

### Parent

Object

### Methods

- ::new
- #check_cert
- #check_chain
- #check_data
- #check_key
- #check_root
- #check_trust
- #verify
- #verify_signatures

### Included Modules

- Gem::UserInteraction

### Class/Module Index

Quicksearch

- Gem::AvailableSet
- Gem::BasicSpecification
- Gem::Command
- Gem::CommandLineError
- Gem::CommandManager
- Gem::Commands
- Gem::Commands::BuildCommand
- Gem::Commands::CertCommand
- Gem::Commands::CheckCommand
- Gem::Commands::CleanupCommand
- Gem::Commands::ContentsCommand
- Gem::Commands::DependencyCommand
- Gem::Commands::EnvironmentCommand
- Gem::Commands::FetchCommand
- Gem::Commands::GenerateIndexCommand
- Gem::Commands::HelpCommand
- Gem::Commands::InstallCommand
- Gem::Commands::ListCommand
- Gem::Commands::LockCommand
- Gem::Commands::MirrorCommand
- Gem::Commands::OpenCommand
- Gem::Commands::OutdatedCommand
- Gem::Commands::OwnerCommand
- Gem::Commands::PristineCommand
- Gem::Commands::PushCommand
- Gem::Commands::QueryCommand
- Gem::Commands::RdocCommand
- Gem::Commands::SearchCommand
- Gem::Commands::ServerCommand
- Gem::Commands::SetupCommand
- Gem::Commands::SourcesCommand
- Gem::Commands::SpecificationCommand
- Gem::Commands::StaleCommand
- Gem::Commands::UninstallCommand
- Gem::Commands::UnpackCommand
- Gem::Commands::UpdateCommand
- Gem::Commands::WhichCommand
- Gem::Commands::YankCommand
- Gem::ConfigFile
- Gem::ConfigFile::Psych
- Gem::ConflictError
- Gem::ConsoleUI
- Gem::DefaultUserInteraction
- Gem::Dependency
- Gem::DependencyError
- Gem::DependencyInstaller
- Gem::DependencyList
- Gem::DependencyRemovalException
- Gem::DependencyResolutionError
- Gem::Deprecate
- Gem::Doctor
- Gem::DocumentError
- Gem::EndOfYAMLException
- Gem::ErrorReason
- Gem::Exception
- Gem::Ext
- Gem::Ext::BuildError
- Gem::Ext::Builder
- Gem::Ext::CmakeBuilder
- Gem::Ext::ConfigureBuilder
- Gem::Ext::ExtConfBuilder
- Gem::Ext::RakeBuilder
- Gem::FakeFetcher
- Gem::FilePermissionError
- Gem::FormatException
- Gem::GemNotFoundException
- Gem::GemNotInHomeException
- Gem::GemRunner
- Gem::GemcutterUtilities
- Gem::ImpossibleDependenciesError
- Gem::Indexer
- Gem::InstallError
- Gem::InstallUpdateOptions
- Gem::Installer
- Gem::InstallerTestCase
- Gem::InvalidSpecificationException
- Gem::List
- Gem::LoadError
- Gem::LocalRemoteOptions
- Gem::MockGemUi
- Gem::MockGemUi::InputEOFError
- Gem::MockGemUi::SystemExitException
- Gem::MockGemUi::TTY
- Gem::MockGemUi::TermError
- Gem::NameTuple
- Gem::NoAliasYAMLTree
- Gem::OperationNotSupportedError
- Gem::Package::DigestIO
- Gem::Package::Error
- Gem::Package::FormatError
- Gem::Package::NonSeekableIO
- Gem::Package::Old
- Gem::Package::PathError
- Gem::Package::TarHeader
- Gem::Package::TarInvalidError
- Gem::Package::TarReader
- Gem::Package::TarReader::Entry
- Gem::Package::TarReader::UnexpectedEOF
- Gem::Package::TarTestCase
- Gem::Package::TarWriter
- Gem::Package::TarWriter::BoundedStream
- Gem::Package::TarWriter::FileOverflow
- Gem::Package::TarWriter::RestrictedStream
- Gem::Package::TooLongFileName
- Gem::PackageTask
- Gem::PathSupport
- Gem::Platform
- Gem::PlatformMismatch
- Gem::RemoteError
- Gem::RemoteFetcher
- Gem::RemoteFetcher::FetchError
- Gem::RemoteFetcher::UnknownHostError
- Gem::RemoteInstallationCancelled
- Gem::RemoteInstallationSkipped
- Gem::RemoteSourceException
- Gem::Request::ConnectionPools
- Gem::Request::ConnectionPools::Net
- Gem::RequestSet
- Gem::RequestSet::GemDependencyAPI
- Gem::RequestSet::Lockfile
- Gem::RequestSet::Lockfile::ParseError
- Gem::Requirement
- Gem::Requirement::BadRequirementError
- Gem::Resolver
- Gem::Resolver::APISet
- Gem::Resolver::APISpecification
- Gem::Resolver::ActivationRequest
- Gem::Resolver::BestSet
- Gem::Resolver::ComposedSet
- Gem::Resolver::Conflict
- Gem::Resolver::CurrentSet
- Gem::Resolver::DependencyRequest
- Gem::Resolver::GitSet
- Gem::Resolver::GitSpecification
- Gem::Resolver::IndexSet
- Gem::Resolver::IndexSpecification
- Gem::Resolver::InstalledSpecification
- Gem::Resolver::InstallerSet
- Gem::Resolver::LocalSpecification
- Gem::Resolver::LockSet
- Gem::Resolver::LockSpecification
- Gem::Resolver::RequirementList
- Gem::Resolver::Set
- Gem::Resolver::SpecSpecification
- Gem::Resolver::Specification
- Gem::Resolver::Stats
- Gem::Resolver::VendorSet
- Gem::Resolver::VendorSpecification
- Gem::RubyVersionMismatch
- Gem::Security
- Gem::Security::Exception
- Gem::Security::Policy
- Gem::Security::Signer
- Gem::Security::TrustDir
- Gem::Server
- Gem::SilentUI
- Gem::Source
- Gem::Source::Git
- Gem::Source::Installed
- Gem::Source::Local
- Gem::Source::Lock
- Gem::Source::SpecificFile
- Gem::Source::Vendor
- Gem::SourceFetchProblem
- Gem::SourceList
- Gem::SpecFetcher
- Gem::SpecificGemNotFoundException
- Gem::Specification
- Gem::StreamUI
- Gem::StreamUI::SilentDownloadReporter
- Gem::StreamUI::SilentProgressReporter
- Gem::StreamUI::SimpleProgressReporter
- Gem::StreamUI::VerboseDownloadReporter
- Gem::StreamUI::VerboseProgressReporter
- Gem::StringSink
- Gem::StringSource
- Gem::StubSpecification
- Gem::SystemExitException
- Gem::TestCase
- Gem::TestCase::SpecFetcherSetup
- Gem::TestCase::StaticSet
- Gem::Text
- Gem::Uninstaller
- Gem::UnsatisfiableDependencyError
- Gem::UriFormatter
- Gem::UserInteraction
- Gem::Util
- Gem::Validator
- Gem::VerificationError
- Gem::Version
- Gem::VersionOption
- Kernel
- Object
- OpenSSL
- TempIO
- YAML::Syck
- YAML::Syck

No matching classes.

# Gem::Security::Policy

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.

### Attributes

name[R]
only_signed[RW]
only_trusted[RW]
to_s[R]
verify_chain[RW]
verify_data[RW]
verify_root[RW]
verify_signer[RW]

### Public Class Methods

new(name, policy = {}) click to toggle source

Create a new Gem::Security::Policy object with the given mode and options.

                   # File rubygems/security/policy.rb, line 26
    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

### Public Instance Methods

check_cert(signer, issuer, time) click to toggle source

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 87
    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 then
        raise Gem::Security::Exception,
              "#{message} not valid before #{not_before}"
      end

      if not_after = signer.not_after and not_after < time then
        raise Gem::Security::Exception, "#{message} not valid after #{not_after}"
      end

      if issuer and not signer.verify issuer.public_key then
        raise Gem::Security::Exception,
              "#{message} was not issued by #{issuer.subject}"
      end

      true
    end

check_chain(chain, time) click to toggle source

Verifies each certificate in `chain` has signed the following certificate and is valid for the given `time`.

                   # File rubygems/security/policy.rb, line 57
    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

check_data(public_key, digest, signature, data) click to toggle source

Verifies that `data` matches the `signature` created by `public_key` and the `digest` algorithm.

                   # File rubygems/security/policy.rb, line 76
    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

check_key(signer, key) click to toggle source

Ensures the public key of `key` matches the public key in `signer`

                   # File rubygems/security/policy.rb, line 113
    def check_key signer, key
      unless signer and key then
        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

check_root(chain, time) click to toggle source

Ensures the root certificate in `chain` is self-signed and valid for `time`.

                   # File rubygems/security/policy.rb, line 131
    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

check_trust(chain, digester, trust_dir) click to toggle source

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 150
    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 then
        message = "root cert #{root.subject} is not trusted"

        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

verify(chain, key = nil, digests = {}) click to toggle source

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 210
    def verify chain, key = nil, digests = {}, signatures = {},
               full_name = '(unknown)'
      if signatures.empty? then
        if @only_signed then
          raise Gem::Security::Exception,
            "unsigned gems are not allowed by the #{name} policy"
        elsif digests.empty? then
          # 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 then
        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 then
        check_trust chain, digester, trust_dir
      elsif signatures.empty? and digests.empty? then
        # 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

verify_signatures(spec, digests, signatures) click to toggle source

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 282
    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