Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Helper to retrieve CRL URIs from a certificate #275

Merged
merged 2 commits into from
Oct 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions lib/openssl/x509.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,39 @@ def authority_key_identifier
key_id.nil? ? nil : key_id.value
end
end

module CRLDistributionPoints
include Helpers

# Get the distributionPoint fullName URI from the certificate's CRL
# distribution points extension, as described in RFC5280 Section
# 4.2.1.13
#
# Returns an array of strings or nil or raises ASN1::ASN1Error.
def crl_uris
ext = find_extension("crlDistributionPoints")
return nil if ext.nil?

cdp_asn1 = ASN1.decode(ext.value_der)
if cdp_asn1.tag_class != :UNIVERSAL || cdp_asn1.tag != ASN1::SEQUENCE
raise ASN1::ASN1Error "invalid extension"
end

crl_uris = cdp_asn1.map do |crl_distribution_point|
distribution_point = crl_distribution_point.value.find do |v|
v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
end
full_name = distribution_point&.value&.find do |v|
v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
end
full_name&.value&.find do |v|
v.tag_class == :CONTEXT_SPECIFIC && v.tag == 6 # uniformResourceIdentifier
end
end

crl_uris&.map(&:value)
end
end
end

class Name
Expand Down Expand Up @@ -234,6 +267,7 @@ def cleanup
class Certificate
include Extension::SubjectKeyIdentifier
include Extension::AuthorityKeyIdentifier
include Extension::CRLDistributionPoints

def pretty_print(q)
q.object_group(self) {
Expand Down
16 changes: 16 additions & 0 deletions test/test_x509cert.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,22 @@ def test_extension
assert_equal(ee1_exts[i].first, ext.oid)
assert_equal(ee1_exts[i].last, ext.critical?)
}
assert_nil(ee1_cert.crl_uris)

ef = OpenSSL::X509::ExtensionFactory.new
ef.config = OpenSSL::Config.parse(<<~_cnf_)
[crlDistPts]
URI.1 = http://www.example.com/crl
URI.2 = ldap://ldap.example.com/cn=ca?certificateRevocationList;binary
_cnf_
cdp_cert = generate_cert(@ee1, @rsa1024, 3, ca_cert)
ef.subject_certificate = cdp_cert
cdp_cert.add_extension(ef.create_extension("crlDistributionPoints", "@crlDistPts"))
cdp_cert.sign(@rsa2048, "sha256")
assert_equal(
["http://www.example.com/crl", "ldap://ldap.example.com/cn=ca?certificateRevocationList;binary"],
cdp_cert.crl_uris
)

no_exts_cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
assert_equal nil, no_exts_cert.authority_key_identifier
Expand Down
15 changes: 12 additions & 3 deletions test/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,10 @@ def file_path(category, name)

module_function

def issue_cert(dn, key, serial, extensions, issuer, issuer_key,
not_before: nil, not_after: nil, digest: "sha256")
def generate_cert(dn, key, serial, issuer,
not_before: nil, not_after: nil)
cert = OpenSSL::X509::Certificate.new
issuer = cert unless issuer
issuer_key = key unless issuer_key
cert.version = 2
cert.serial = serial
cert.subject = dn
Expand All @@ -73,6 +72,16 @@ def issue_cert(dn, key, serial, extensions, issuer, issuer_key,
now = Time.now
cert.not_before = not_before || now - 3600
cert.not_after = not_after || now + 3600
cert
end


def issue_cert(dn, key, serial, extensions, issuer, issuer_key,
not_before: nil, not_after: nil, digest: "sha256")
cert = generate_cert(dn, key, serial, issuer,
not_before: not_before, not_after: not_after)
issuer = cert unless issuer
issuer_key = key unless issuer_key
ef = OpenSSL::X509::ExtensionFactory.new
ef.subject_certificate = cert
ef.issuer_certificate = issuer
Expand Down