Class: R509::CRL::Administrator

Inherits:
Object
  • Object
show all
Defined in:
lib/r509/crl/administrator.rb

Overview

Used to manage revocations and generate CRLs

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config, reader_writer = R509::CRL::FileReaderWriter.new) ⇒ Administrator

Returns a new instance of Administrator

Parameters:



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/r509/crl/administrator.rb', line 17

def initialize(config, reader_writer = R509::CRL::FileReaderWriter.new)
  @config = config
  unless @config.is_a?(R509::Config::CAConfig)
    raise R509Error, "config must be a kind of R509::Config::CAConfig"
  end

  unless reader_writer.is_a?(R509::CRL::ReaderWriter)
    raise ArgumentError, "argument reader_writer must be a subclass of R509::CRL::ReaderWriter"
  end
  @rw = reader_writer
  @rw.crl_list_file = @config.crl_list_file if @rw.respond_to?(:crl_list_file=)
  @rw.crl_number_file = @config.crl_number_file if @rw.respond_to?(:crl_number_file=)
  @crl_number = @rw.read_number
  @revoked_certs = {}
  @rw.read_list do |serial, reason, revoke_time|
    revoke_cert(serial, reason, revoke_time, false)
  end

  @crl_md = R509::MessageDigest.new(@config.crl_md)
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config



13
14
15
# File 'lib/r509/crl/administrator.rb', line 13

def config
  @config
end

#crl_numberObject (readonly)

Returns the value of attribute crl_number



13
14
15
# File 'lib/r509/crl/administrator.rb', line 13

def crl_number
  @crl_number
end

Instance Method Details

#generate_crl(last_update = Time.at(Time.now.to_i) - @config.crl_start_skew_seconds, next_update = Time.at(Time.now) + @config.crl_validity_hours * 3600) ⇒ R509::CRL::SignedList

Generate the CRL

Parameters:

  • last_update (Time) (defaults to: Time.at(Time.now.to_i) - @config.crl_start_skew_seconds)

    the lastUpdate for the CRL

  • next_update (Time) (defaults to: Time.at(Time.now) + @config.crl_validity_hours * 3600)

    the nextUpdate for the CRL

Returns:



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/r509/crl/administrator.rb', line 104

def generate_crl(last_update = Time.at(Time.now.to_i) - @config.crl_start_skew_seconds, next_update = Time.at(Time.now) + @config.crl_validity_hours * 3600)
  # Time.at(Time.now.to_i) removes sub-second precision. Subsecond precision is irrelevant
  # for CRL update times and makes testing harder.
  crl = create_crl_object(last_update, next_update)

  self.revoked_certs.each do |serial, reason, revoke_time|
    revoked = OpenSSL::X509::Revoked.new
    revoked.serial = OpenSSL::BN.new serial.to_s
    revoked.time = Time.at(revoke_time)
    unless reason.nil?
      enum = OpenSSL::ASN1::Enumerated(reason)
      ext = OpenSSL::X509::Extension.new("CRLReason", enum)
      revoked.add_extension(ext)
    end
    # now add it to the crl
    crl.add_revoked(revoked)
  end

  crl.sign(@config.crl_cert.key.key, @crl_md.digest)
  R509::CRL::SignedList.new(crl)
end

#revoke_cert(serial, reason = nil, revoke_time = Time.now.to_i, write = true) ⇒ Object

Adds a certificate to the revocation list. After calling you must call generate_crl to sign a new CRL

reason codes defined by rfc 5280

CRLReason ::= ENUMERATED {

unspecified       (0),
keyCompromise       (1),
cACompromise        (2),
affiliationChanged    (3),
superseded        (4),
cessationOfOperation    (5),
certificateHold     (6),
removeFromCRL       (8),
privilegeWithdrawn    (9),
aACompromise       (10) }

Parameters:

  • serial (Integer)

    serial number of the certificate to revoke

  • reason (Integer, nil) (defaults to: nil)

    reason for revocation

  • revoke_time (Integer) (defaults to: Time.now.to_i)
  • write (Boolean) (defaults to: true)

    whether or not to write the revocation event. Should only be false if you're doing an initial load



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/r509/crl/administrator.rb', line 71

def revoke_cert(serial, reason = nil, revoke_time = Time.now.to_i, write = true)
  unless reason.nil?
    if !reason.is_a?(Integer) || !reason.between?(0, 10) || reason == 7
      raise ArgumentError, "Revocation reason must be integer 0-10 (excluding 7) or nil"
    end
  end

  serial = serial.to_i
  revoke_time = revoke_time.to_i
  if revoked?(serial)
    raise R509::R509Error, "Cannot revoke a previously revoked certificate"
  end
  @revoked_certs[serial] = { :reason => reason, :revoke_time => revoke_time }
  if write == true
    @rw.write_list_entry(serial, revoke_time, reason)
  end
  nil
end

#revoked?(serial) ⇒ Boolean

Indicates whether the serial number has been revoked, or not.

Parameters:

  • serial (Integer)

    The serial number we want to check

Returns:

  • (Boolean)

    True if the serial number was revoked. False, otherwise.



42
43
44
# File 'lib/r509/crl/administrator.rb', line 42

def revoked?(serial)
  @revoked_certs.key?(serial.to_i)
end

#revoked_cert(serial) ⇒ Array

Returns serial, reason, revoke_time tuple

Returns:

  • (Array)

    serial, reason, revoke_time tuple



47
48
49
# File 'lib/r509/crl/administrator.rb', line 47

def revoked_cert(serial)
  @revoked_certs[serial]
end

#revoked_certsArray<Array>

Returns an array of serial, reason, revoke_time tuples.

Returns:

  • (Array<Array>)

    Returns an array of serial, reason, revoke_time tuples.



128
129
130
131
132
133
134
# File 'lib/r509/crl/administrator.rb', line 128

def revoked_certs
  ret = []
  @revoked_certs.keys.sort.each do |serial|
    ret << [serial, @revoked_certs[serial][:reason], @revoked_certs[serial][:revoke_time]]
  end
  ret
end

#unrevoke_cert(serial) ⇒ Object

Remove serial from revocation list. After unrevoking you must call generate_crl to sign a new CRL

Parameters:

  • serial (Integer)

    serial number of the certificate to remove from revocation



93
94
95
96
97
# File 'lib/r509/crl/administrator.rb', line 93

def unrevoke_cert(serial)
  @revoked_certs.delete(serial)
  @rw.remove_list_entry(serial)
  nil
end