class R509::Cert::Extensions::CertificatePolicies

RFC 5280 Description (see: www.ietf.org/rfc/rfc5280.txt)

The certificate policies extension contains a sequence of one or more policy information terms, each of which consists of an object identifier (OID) and optional qualifiers. Optional qualifiers, which MAY be present, are not expected to change the definition of the policy. A certificate policy OID MUST NOT appear more than once in a certificate policies extension.

You can use this extension to parse an existing extension for easy access to the contents or create a new one.

Constants

OID

friendly name for CP OID

Attributes

policies[R]

@return [Array] Array of R509::Cert::Extensions::PolicyObjects::PolicyInformation objects

Public Class Methods

new(arg) click to toggle source

This method takes a hash or an existing Extension object to parse. The hash must contain a :value that is an array of policy information. See the example.

@option arg :value [Array] Array of hashes in the format shown in the examples. This is a complex hash. @option arg :critical [Boolean] (false) @example

R509::Cert::Extensions::CertificatePolicies.new(:value => [
  { :policy_identifier => "2.16.840.1.12345.1.2.3.4.1",
    :cps_uris => ["http://example.com/cps","http://other.com/cps"],
    :user_notices => [ {:explicit_text => "thing", :organization => "my org", :notice_numbers => [1,2,3,4]} ]
 }
])
Calls superclass method
# File lib/r509/cert/extensions/certificate_policies.rb, line 36
def initialize(arg)
  unless R509::Cert::Extensions.is_extension?(arg)
    arg = build_extension(arg)
  end

  super(arg)
  parse_extension
end

Public Instance Methods

to_h() click to toggle source

@return [Hash]

# File lib/r509/cert/extensions/certificate_policies.rb, line 46
def to_h
  {
    :critical => self.critical?,
    :value => @policies.map { |policy| policy.to_h }
  }
end
to_yaml() click to toggle source

@return [YAML]

# File lib/r509/cert/extensions/certificate_policies.rb, line 54
def to_yaml
  self.to_h.to_yaml
end

Private Instance Methods

build_conf(section, hash, index) click to toggle source
# File lib/r509/cert/extensions/certificate_policies.rb, line 85
def build_conf(section, hash, index)
  conf = ["[#{section}]"]
  conf.push "policyIdentifier=#{hash[:policy_identifier]}" unless hash[:policy_identifier].nil?
  hash[:cps_uris].each_with_index do |cps, idx|
    conf.push "CPS.#{idx + 1}=\"#{cps}\""
  end if hash[:cps_uris].respond_to?(:each_with_index)

  user_notice_confs = []
  hash[:user_notices].each_with_index do |un, k|
    conf.push "userNotice.#{k + 1}=@user_notice#{k + 1}#{index}"
    user_notice_confs.push "[user_notice#{k + 1}#{index}]"
    user_notice_confs.push "explicitText=\"#{un[:explicit_text]}\"" unless un[:explicit_text].nil?
    # if org is supplied notice numbers is also required (and vice versa). enforced in CAProfile
    user_notice_confs.push "organization=\"#{un[:organization]}\"" unless un[:organization].nil?
    user_notice_confs.push "noticeNumbers=\"#{un[:notice_numbers].join(",")}\"" unless un[:notice_numbers].nil?
  end if hash[:user_notices].is_a?(Array)

  conf.concat(user_notice_confs)
  conf.join "\n"
end
build_extension(arg) click to toggle source
# File lib/r509/cert/extensions/certificate_policies.rb, line 71
def build_extension(arg)
  validate_certificate_policies(arg[:value])
  conf = []
  policy_names = ["ia5org"]
  arg[:value].each_with_index do |policy, i|
    conf << build_conf("certPolicies#{i}", policy, i)
    policy_names << "@certPolicies#{i}"
  end
  ef = OpenSSL::X509::ExtensionFactory.new
  ef.config = OpenSSL::Config.parse(conf.join("\n"))
  critical = R509::Cert::Extensions.calculate_critical(arg[:critical], false)
  ef.create_extension("certificatePolicies", policy_names.join(","), critical)
end
parse_extension() click to toggle source
# File lib/r509/cert/extensions/certificate_policies.rb, line 60
def parse_extension
  @policies = []
  data = R509::ASN1.get_extension_payload(self)

  # each element of this sequence should be part of a policy + qualifiers
  #   certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
  data.each do |cp|
    @policies << PolicyInformation.new(cp)
  end if data.respond_to?(:each)
end
validate_certificate_policies(policies) click to toggle source

validates the structure of the certificate policies array

# File lib/r509/cert/extensions/certificate_policies.rb, line 107
def validate_certificate_policies(policies)
  raise ArgumentError, "Not a valid certificate policy structure. Must be an array of hashes" unless policies.is_a?(Array)

  policies.each do |policy|
    raise ArgumentError, "Each policy requires a policy identifier" if policy[:policy_identifier].nil?
    raise ArgumentError, "CPS URIs must be an array of strings" if policy[:cps_uris] && !policy[:cps_uris].respond_to?(:each)
    unless policy[:user_notices].nil?
      raise ArgumentError, "User notices must be an array of hashes" unless policy[:user_notices].respond_to?(:each)
      policy[:user_notices].each do |un|
        raise ArgumentError, "If you provide an organization you must provide notice numbers" if un[:organization] && un[:notice_numbers].nil?
        raise ArgumentError, "If you provide notice numbers you must provide an organization" if un[:notice_numbers] && un[:organization].nil?
      end
    end
  end
end