Skip to content

Commit 71f4fef

Browse files
committed
x509: fix handling of multiple URIs in Certificate#crl_uris
The implementation of OpenSSL::X509::Certificate#crl_uris makes the assumption that each DistributionPoint in the CRL distribution points extension contains a single general name of type URI. This is not guaranteed by RFC 5280. A DistributionPoint may contain zero or more than one URIs. Let's include all URIs found in the extension. If only non-URI pointers are found, return nil. Fixes: #775
1 parent 461cfcb commit 71f4fef

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

lib/openssl/x509.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ module CRLDistributionPoints
122122
include Helpers
123123

124124
# Get the distributionPoint fullName URI from the certificate's CRL
125-
# distribution points extension, as described in RFC5280 Section
126-
# 4.2.1.13
125+
# distribution points extension, as described in RFC 5280 Section
126+
# 4.2.1.13.
127127
#
128128
# Returns an array of strings or nil or raises ASN1::ASN1Error.
129129
def crl_uris
@@ -135,19 +135,19 @@ def crl_uris
135135
raise ASN1::ASN1Error, "invalid extension"
136136
end
137137

138-
crl_uris = cdp_asn1.map do |crl_distribution_point|
138+
crl_uris = cdp_asn1.flat_map do |crl_distribution_point|
139139
distribution_point = crl_distribution_point.value.find do |v|
140140
v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
141141
end
142142
full_name = distribution_point&.value&.find do |v|
143143
v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
144144
end
145-
full_name&.value&.find do |v|
145+
full_name&.value&.select do |v|
146146
v.tag_class == :CONTEXT_SPECIFIC && v.tag == 6 # uniformResourceIdentifier
147147
end
148148
end
149149

150-
crl_uris&.map(&:value)
150+
crl_uris.empty? ? nil : crl_uris.map(&:value)
151151
end
152152
end
153153

test/openssl/test_x509cert.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,39 @@ def test_crl_uris
151151
)
152152
end
153153

154+
def test_crl_uris_multiple_general_names
155+
# Single DistributionPoint contains multiple general names of type URI
156+
ef = OpenSSL::X509::ExtensionFactory.new
157+
ef.config = OpenSSL::Config.parse(<<~_cnf_)
158+
[crlDistPts_section]
159+
fullname = URI:http://www.example.com/crl, URI:ldap://ldap.example.com/cn=ca?certificateRevocationList;binary
160+
_cnf_
161+
cdp_cert = generate_cert(@ee1, @rsa2048, 3, nil)
162+
ef.subject_certificate = cdp_cert
163+
cdp_cert.add_extension(ef.create_extension("crlDistributionPoints", "crlDistPts_section"))
164+
cdp_cert.sign(@rsa2048, "sha256")
165+
assert_equal(
166+
["http://www.example.com/crl", "ldap://ldap.example.com/cn=ca?certificateRevocationList;binary"],
167+
cdp_cert.crl_uris
168+
)
169+
end
170+
171+
def test_crl_uris_no_uris
172+
# The only DistributionPointName is a directoryName
173+
ef = OpenSSL::X509::ExtensionFactory.new
174+
ef.config = OpenSSL::Config.parse(<<~_cnf_)
175+
[crlDistPts_section]
176+
fullname = dirName:dirname_section
177+
[dirname_section]
178+
CN = dirname
179+
_cnf_
180+
cdp_cert = generate_cert(@ee1, @rsa2048, 3, nil)
181+
ef.subject_certificate = cdp_cert
182+
cdp_cert.add_extension(ef.create_extension("crlDistributionPoints", "crlDistPts_section"))
183+
cdp_cert.sign(@rsa2048, "sha256")
184+
assert_nil(cdp_cert.crl_uris)
185+
end
186+
154187
def test_aia_missing
155188
cert = issue_cert(@ee1, @rsa2048, 1, [], nil, nil)
156189
assert_nil(cert.ca_issuer_uris)

0 commit comments

Comments
 (0)