Skip to content

Commit c621fc1

Browse files
committed
[test] port over from MRI suite to reproduce #113 regression
(introduced in 0.9.18)
1 parent 7308da1 commit c621fc1

File tree

1 file changed

+173
-1
lines changed

1 file changed

+173
-1
lines changed

src/test/ruby/x509/test_x509store.rb

Lines changed: 173 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# coding: US-ASCII
22
require File.expand_path('../test_helper', File.dirname(__FILE__))
3+
require File.expand_path('../ssl/test_helper', File.dirname(__FILE__))
34

45
class TestX509Store < TestCase
56

@@ -80,7 +81,7 @@ def test_use_non_existing_cert_file
8081
assert ! store.verify(@cert)
8182
end
8283

83-
def test_verfy_with_wrong_argument
84+
def test_verify_with_wrong_argument
8485
store = OpenSSL::X509::Store.new
8586
assert_raise(TypeError) { store.verify( 'not a cert object' ) }
8687
end
@@ -151,4 +152,175 @@ def test_adding_pem_to_store
151152
end
152153
end
153154

155+
def test_verify
156+
@rsa1024 = OpenSSL::PKey::RSA.new SSLTestHelper::TEST_KEY_RSA1024 # OpenSSL::TestUtils::TEST_KEY_RSA1024
157+
@rsa2048 = OpenSSL::PKey::RSA.new SSLTestHelper::TEST_KEY_RSA2048 # OpenSSL::TestUtils::TEST_KEY_RSA2048
158+
@dsa256 = OpenSSL::PKey::DSA.new SSLTestHelper::TEST_KEY_DSA256 # OpenSSL::TestUtils::TEST_KEY_DSA256
159+
@dsa512 = OpenSSL::PKey::DSA.new SSLTestHelper::TEST_KEY_DSA512 # OpenSSL::TestUtils::TEST_KEY_DSA512
160+
@ca1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA1")
161+
@ca2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA2")
162+
@ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1")
163+
@ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2")
164+
165+
now = Time.at(Time.now.to_i)
166+
ca_exts = [
167+
["basicConstraints","CA:TRUE",true],
168+
["keyUsage","cRLSign,keyCertSign",true],
169+
]
170+
ee_exts = [
171+
["keyUsage","keyEncipherment,digitalSignature",true],
172+
]
173+
ca1_cert = issue_cert(@ca1, @rsa2048, 1, now, now+3600, ca_exts,
174+
nil, nil, OpenSSL::Digest::SHA1.new)
175+
ca2_cert = issue_cert(@ca2, @rsa1024, 2, now, now+1800, ca_exts,
176+
ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
177+
ee1_cert = issue_cert(@ee1, @dsa256, 10, now, now+1800, ee_exts,
178+
ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
179+
ee2_cert = issue_cert(@ee2, @dsa512, 20, now, now+1800, ee_exts,
180+
ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
181+
ee3_cert = issue_cert(@ee2, @dsa512, 30, now-100, now-1, ee_exts,
182+
ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
183+
ee4_cert = issue_cert(@ee2, @dsa512, 40, now+1000, now+2000, ee_exts,
184+
ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
185+
186+
revoke_info = []
187+
crl1 = issue_crl(revoke_info, 1, now, now+1800, [],
188+
ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
189+
revoke_info = [ [2, now, 1], ]
190+
crl1_2 = issue_crl(revoke_info, 2, now, now+1800, [],
191+
ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
192+
revoke_info = [ [20, now, 1], ]
193+
crl2 = issue_crl(revoke_info, 1, now, now+1800, [],
194+
ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
195+
revoke_info = []
196+
crl2_2 = issue_crl(revoke_info, 2, now-100, now-1, [],
197+
ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
198+
199+
assert_equal(true, ca1_cert.verify(ca1_cert.public_key)) # self signed
200+
assert_equal(true, ca2_cert.verify(ca1_cert.public_key)) # issued by ca1
201+
assert_equal(true, ee1_cert.verify(ca2_cert.public_key)) # issued by ca2
202+
assert_equal(true, ee2_cert.verify(ca2_cert.public_key)) # issued by ca2
203+
assert_equal(true, ee3_cert.verify(ca2_cert.public_key)) # issued by ca2
204+
assert_equal(true, crl1.verify(ca1_cert.public_key)) # issued by ca1
205+
assert_equal(true, crl1_2.verify(ca1_cert.public_key)) # issued by ca1
206+
assert_equal(true, crl2.verify(ca2_cert.public_key)) # issued by ca2
207+
assert_equal(true, crl2_2.verify(ca2_cert.public_key)) # issued by ca2
208+
209+
store = OpenSSL::X509::Store.new
210+
assert_equal(false, store.verify(ca1_cert))
211+
assert_not_equal(OpenSSL::X509::V_OK, store.error)
212+
213+
assert_equal(false, store.verify(ca2_cert))
214+
assert_not_equal(OpenSSL::X509::V_OK, store.error)
215+
216+
store.add_cert(ca1_cert)
217+
assert_equal(true, store.verify(ca2_cert))
218+
assert_equal(OpenSSL::X509::V_OK, store.error)
219+
assert_equal("ok", store.error_string)
220+
chain = store.chain
221+
assert_equal(2, chain.size)
222+
assert_equal(@ca2.to_der, chain[0].subject.to_der)
223+
assert_equal(@ca1.to_der, chain[1].subject.to_der)
224+
225+
store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
226+
assert_equal(false, store.verify(ca2_cert))
227+
assert_not_equal(OpenSSL::X509::V_OK, store.error)
228+
229+
store.purpose = OpenSSL::X509::PURPOSE_CRL_SIGN
230+
assert_equal(true, store.verify(ca2_cert))
231+
assert_equal(OpenSSL::X509::V_OK, store.error)
232+
233+
store.add_cert(ca2_cert)
234+
store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
235+
assert_equal(true, store.verify(ee1_cert))
236+
assert_equal(true, store.verify(ee2_cert))
237+
assert_equal(OpenSSL::X509::V_OK, store.error)
238+
assert_equal("ok", store.error_string)
239+
chain = store.chain
240+
assert_equal(3, chain.size)
241+
assert_equal(@ee2.to_der, chain[0].subject.to_der)
242+
assert_equal(@ca2.to_der, chain[1].subject.to_der)
243+
assert_equal(@ca1.to_der, chain[2].subject.to_der)
244+
assert_equal(false, store.verify(ee3_cert))
245+
assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error)
246+
assert_match(/expire/i, store.error_string)
247+
assert_equal(false, store.verify(ee4_cert))
248+
assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error)
249+
assert_match(/not yet valid/i, store.error_string)
250+
251+
store = OpenSSL::X509::Store.new
252+
store.add_cert(ca1_cert)
253+
store.add_cert(ca2_cert)
254+
store.time = now + 1500
255+
assert_equal(true, store.verify(ca1_cert))
256+
assert_equal(true, store.verify(ca2_cert))
257+
assert_equal(true, store.verify(ee4_cert))
258+
store.time = now + 1900
259+
assert_equal(true, store.verify(ca1_cert))
260+
assert_equal(false, store.verify(ca2_cert))
261+
assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error)
262+
assert_equal(false, store.verify(ee4_cert))
263+
assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error)
264+
store.time = now + 4000
265+
assert_equal(false, store.verify(ee1_cert))
266+
assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error)
267+
assert_equal(false, store.verify(ee4_cert))
268+
assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error)
269+
270+
# the underlying X509 struct caches the result of the last
271+
# verification for signature and not-before. so the following code
272+
# rebuilds new objects to avoid site effect.
273+
store.time = Time.now - 4000
274+
assert_equal(false, store.verify(OpenSSL::X509::Certificate.new(ca2_cert)))
275+
assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error)
276+
assert_equal(false, store.verify(OpenSSL::X509::Certificate.new(ee1_cert)))
277+
assert_equal(OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID, store.error)
278+
279+
return unless defined?(OpenSSL::X509::V_FLAG_CRL_CHECK)
280+
281+
store = OpenSSL::X509::Store.new
282+
store.purpose = OpenSSL::X509::PURPOSE_ANY
283+
store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK
284+
store.add_cert(ca1_cert)
285+
store.add_crl(crl1) # revoke no cert
286+
store.add_crl(crl2) # revoke ee2_cert
287+
assert_equal(true, store.verify(ca1_cert))
288+
assert_equal(true, store.verify(ca2_cert))
289+
assert_equal(true, store.verify(ee1_cert, [ca2_cert]))
290+
assert_equal(false, store.verify(ee2_cert, [ca2_cert]))
291+
292+
store = OpenSSL::X509::Store.new
293+
store.purpose = OpenSSL::X509::PURPOSE_ANY
294+
store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK
295+
store.add_cert(ca1_cert)
296+
store.add_crl(crl1_2) # revoke ca2_cert
297+
store.add_crl(crl2) # revoke ee2_cert
298+
assert_equal(true, store.verify(ca1_cert))
299+
assert_equal(false, store.verify(ca2_cert))
300+
assert_equal(true, store.verify(ee1_cert, [ca2_cert]),
301+
"This test is expected to be success with OpenSSL 0.9.7c or later.")
302+
assert_equal(false, store.verify(ee2_cert, [ca2_cert]))
303+
304+
store.flags =
305+
OpenSSL::X509::V_FLAG_CRL_CHECK|OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
306+
assert_equal(true, store.verify(ca1_cert))
307+
assert_equal(false, store.verify(ca2_cert))
308+
assert_equal(false, store.verify(ee1_cert, [ca2_cert]))
309+
assert_equal(false, store.verify(ee2_cert, [ca2_cert]))
310+
311+
store = OpenSSL::X509::Store.new
312+
store.purpose = OpenSSL::X509::PURPOSE_ANY
313+
store.flags =
314+
OpenSSL::X509::V_FLAG_CRL_CHECK|OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
315+
store.add_cert(ca1_cert)
316+
store.add_cert(ca2_cert)
317+
store.add_crl(crl1)
318+
store.add_crl(crl2_2) # issued by ca2 but expired.
319+
assert_equal(true, store.verify(ca1_cert))
320+
assert_equal(true, store.verify(ca2_cert))
321+
assert_equal(false, store.verify(ee1_cert))
322+
assert_equal(OpenSSL::X509::V_ERR_CRL_HAS_EXPIRED, store.error)
323+
assert_equal(false, store.verify(ee2_cert))
324+
end
325+
154326
end

0 commit comments

Comments
 (0)