r509 0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. data/README.md +447 -0
  2. data/Rakefile +38 -0
  3. data/bin/r509 +96 -0
  4. data/bin/r509-parse +35 -0
  5. data/doc/R509.html +154 -0
  6. data/doc/R509/Cert.html +3954 -0
  7. data/doc/R509/Cert/Extensions.html +360 -0
  8. data/doc/R509/Cert/Extensions/AuthorityInfoAccess.html +391 -0
  9. data/doc/R509/Cert/Extensions/AuthorityKeyIdentifier.html +148 -0
  10. data/doc/R509/Cert/Extensions/BasicConstraints.html +482 -0
  11. data/doc/R509/Cert/Extensions/CrlDistributionPoints.html +316 -0
  12. data/doc/R509/Cert/Extensions/ExtendedKeyUsage.html +780 -0
  13. data/doc/R509/Cert/Extensions/KeyUsage.html +1230 -0
  14. data/doc/R509/Cert/Extensions/SubjectAlternativeName.html +467 -0
  15. data/doc/R509/Cert/Extensions/SubjectKeyIdentifier.html +216 -0
  16. data/doc/R509/CertificateAuthority.html +126 -0
  17. data/doc/R509/CertificateAuthority/Signer.html +855 -0
  18. data/doc/R509/Config.html +127 -0
  19. data/doc/R509/Config/CaConfig.html +2144 -0
  20. data/doc/R509/Config/CaConfigPool.html +599 -0
  21. data/doc/R509/Config/CaProfile.html +656 -0
  22. data/doc/R509/Config/SubjectItemPolicy.html +578 -0
  23. data/doc/R509/Crl.html +126 -0
  24. data/doc/R509/Crl/Administrator.html +2077 -0
  25. data/doc/R509/Crl/Parser.html +1224 -0
  26. data/doc/R509/Csr.html +2248 -0
  27. data/doc/R509/IOHelpers.html +564 -0
  28. data/doc/R509/MessageDigest.html +396 -0
  29. data/doc/R509/NameSanitizer.html +319 -0
  30. data/doc/R509/Ocsp.html +128 -0
  31. data/doc/R509/Ocsp/Request.html +126 -0
  32. data/doc/R509/Ocsp/Request/Nonce.html +160 -0
  33. data/doc/R509/Ocsp/Response.html +837 -0
  34. data/doc/R509/OidMapper.html +393 -0
  35. data/doc/R509/PrivateKey.html +1647 -0
  36. data/doc/R509/R509Error.html +134 -0
  37. data/doc/R509/Spki.html +1424 -0
  38. data/doc/R509/Subject.html +836 -0
  39. data/doc/R509/Validity.html +160 -0
  40. data/doc/R509/Validity/Checker.html +320 -0
  41. data/doc/R509/Validity/DefaultChecker.html +283 -0
  42. data/doc/R509/Validity/DefaultWriter.html +330 -0
  43. data/doc/R509/Validity/Status.html +561 -0
  44. data/doc/R509/Validity/Writer.html +394 -0
  45. data/doc/_index.html +501 -0
  46. data/doc/class_list.html +53 -0
  47. data/doc/css/common.css +1 -0
  48. data/doc/css/full_list.css +57 -0
  49. data/doc/css/style.css +328 -0
  50. data/doc/file.README.html +534 -0
  51. data/doc/file.r509.html +149 -0
  52. data/doc/file_list.html +58 -0
  53. data/doc/frames.html +28 -0
  54. data/doc/index.html +534 -0
  55. data/doc/js/app.js +208 -0
  56. data/doc/js/full_list.js +173 -0
  57. data/doc/js/jquery.js +4 -0
  58. data/doc/methods_list.html +1932 -0
  59. data/doc/top-level-namespace.html +112 -0
  60. data/lib/r509.rb +22 -0
  61. data/lib/r509/cert.rb +414 -0
  62. data/lib/r509/cert/extensions.rb +309 -0
  63. data/lib/r509/certificateauthority.rb +290 -0
  64. data/lib/r509/config.rb +407 -0
  65. data/lib/r509/crl.rb +379 -0
  66. data/lib/r509/csr.rb +324 -0
  67. data/lib/r509/exceptions.rb +5 -0
  68. data/lib/r509/io_helpers.rb +52 -0
  69. data/lib/r509/messagedigest.rb +49 -0
  70. data/lib/r509/ocsp.rb +85 -0
  71. data/lib/r509/oidmapper.rb +32 -0
  72. data/lib/r509/privatekey.rb +185 -0
  73. data/lib/r509/spki.rb +112 -0
  74. data/lib/r509/subject.rb +133 -0
  75. data/lib/r509/validity.rb +92 -0
  76. data/lib/r509/version.rb +4 -0
  77. data/r509.yaml +73 -0
  78. data/spec/cert/extensions_spec.rb +632 -0
  79. data/spec/cert_spec.rb +321 -0
  80. data/spec/certificate_authority_spec.rb +260 -0
  81. data/spec/config_spec.rb +349 -0
  82. data/spec/crl_spec.rb +215 -0
  83. data/spec/csr_spec.rb +302 -0
  84. data/spec/fixtures.rb +233 -0
  85. data/spec/fixtures/cert1.der +0 -0
  86. data/spec/fixtures/cert1.pem +24 -0
  87. data/spec/fixtures/cert1_public_key_modulus.txt +1 -0
  88. data/spec/fixtures/cert3.p12 +0 -0
  89. data/spec/fixtures/cert3.pem +28 -0
  90. data/spec/fixtures/cert3_key.pem +27 -0
  91. data/spec/fixtures/cert3_key_des3.pem +30 -0
  92. data/spec/fixtures/cert4.pem +14 -0
  93. data/spec/fixtures/cert5.pem +30 -0
  94. data/spec/fixtures/cert6.pem +26 -0
  95. data/spec/fixtures/cert_expired.pem +26 -0
  96. data/spec/fixtures/cert_not_yet_valid.pem +26 -0
  97. data/spec/fixtures/cert_san.pem +27 -0
  98. data/spec/fixtures/cert_san2.pem +22 -0
  99. data/spec/fixtures/config_pool_test_minimal.yaml +15 -0
  100. data/spec/fixtures/config_test.yaml +41 -0
  101. data/spec/fixtures/config_test_engine_key.yaml +7 -0
  102. data/spec/fixtures/config_test_engine_no_key_name.yaml +6 -0
  103. data/spec/fixtures/config_test_minimal.yaml +7 -0
  104. data/spec/fixtures/config_test_password.yaml +7 -0
  105. data/spec/fixtures/config_test_various.yaml +100 -0
  106. data/spec/fixtures/crl_list_file.txt +1 -0
  107. data/spec/fixtures/crl_with_reason.pem +17 -0
  108. data/spec/fixtures/csr1.der +0 -0
  109. data/spec/fixtures/csr1.pem +17 -0
  110. data/spec/fixtures/csr1_key.der +0 -0
  111. data/spec/fixtures/csr1_key.pem +27 -0
  112. data/spec/fixtures/csr1_key_encrypted_des3.pem +30 -0
  113. data/spec/fixtures/csr1_newlines.pem +32 -0
  114. data/spec/fixtures/csr1_no_begin_end.pem +15 -0
  115. data/spec/fixtures/csr1_public_key_modulus.txt +1 -0
  116. data/spec/fixtures/csr2.pem +15 -0
  117. data/spec/fixtures/csr2_key.pem +27 -0
  118. data/spec/fixtures/csr3.pem +16 -0
  119. data/spec/fixtures/csr4.pem +25 -0
  120. data/spec/fixtures/csr_dsa.pem +15 -0
  121. data/spec/fixtures/csr_invalid_signature.pem +13 -0
  122. data/spec/fixtures/dsa_key.pem +20 -0
  123. data/spec/fixtures/key4.pem +27 -0
  124. data/spec/fixtures/key4_encrypted_des3.pem +30 -0
  125. data/spec/fixtures/missing_key_identifier_ca.cer +21 -0
  126. data/spec/fixtures/missing_key_identifier_ca.key +27 -0
  127. data/spec/fixtures/ocsptest.r509.local.pem +27 -0
  128. data/spec/fixtures/ocsptest.r509.local_ocsp_request.der +0 -0
  129. data/spec/fixtures/ocsptest2.r509.local.pem +27 -0
  130. data/spec/fixtures/second_ca.cer +26 -0
  131. data/spec/fixtures/second_ca.key +27 -0
  132. data/spec/fixtures/spkac.der +0 -0
  133. data/spec/fixtures/spkac.txt +1 -0
  134. data/spec/fixtures/spkac_dsa.txt +1 -0
  135. data/spec/fixtures/stca.pem +22 -0
  136. data/spec/fixtures/stca_ocsp_request.der +0 -0
  137. data/spec/fixtures/stca_ocsp_response.der +0 -0
  138. data/spec/fixtures/test1.csr +17 -0
  139. data/spec/fixtures/test_ca.cer +22 -0
  140. data/spec/fixtures/test_ca.key +28 -0
  141. data/spec/fixtures/test_ca.p12 +0 -0
  142. data/spec/fixtures/test_ca_des3.key +30 -0
  143. data/spec/fixtures/test_ca_ocsp.cer +26 -0
  144. data/spec/fixtures/test_ca_ocsp.key +27 -0
  145. data/spec/fixtures/test_ca_ocsp.p12 +0 -0
  146. data/spec/fixtures/test_ca_ocsp_chain.txt +48 -0
  147. data/spec/fixtures/test_ca_ocsp_response.der +0 -0
  148. data/spec/fixtures/test_ca_subroot.cer +26 -0
  149. data/spec/fixtures/test_ca_subroot.key +27 -0
  150. data/spec/fixtures/test_ca_subroot_ocsp.cer +25 -0
  151. data/spec/fixtures/test_ca_subroot_ocsp.key +27 -0
  152. data/spec/fixtures/test_ca_subroot_ocsp_response.der +0 -0
  153. data/spec/fixtures/unknown_oid.csr +17 -0
  154. data/spec/message_digest_spec.rb +89 -0
  155. data/spec/ocsp_spec.rb +111 -0
  156. data/spec/oid_mapper_spec.rb +31 -0
  157. data/spec/privatekey_spec.rb +198 -0
  158. data/spec/spec_helper.rb +14 -0
  159. data/spec/spki_spec.rb +157 -0
  160. data/spec/subject_spec.rb +203 -0
  161. data/spec/validity_spec.rb +98 -0
  162. metadata +257 -0
@@ -0,0 +1,14 @@
1
+ if (RUBY_VERSION.split('.')[1].to_i > 8)
2
+ begin
3
+ require 'simplecov'
4
+ SimpleCov.start
5
+ rescue LoadError
6
+ end
7
+ end
8
+
9
+ $:.unshift File.expand_path("../../lib", __FILE__)
10
+ $:.unshift File.expand_path("../", __FILE__)
11
+ require 'rubygems'
12
+ require 'fixtures'
13
+ require 'rspec'
14
+ require 'r509'
data/spec/spki_spec.rb ADDED
@@ -0,0 +1,157 @@
1
+ require 'spec_helper'
2
+ require 'stringio'
3
+ require 'r509/spki'
4
+
5
+
6
+ describe R509::Spki do
7
+ before :all do
8
+ #also known as SPKAC (signed public key and challenge)
9
+ @spki_dsa = TestFixtures::SPKI_DSA.strip
10
+ @spki = TestFixtures::SPKI.strip
11
+ @spki_der = TestFixtures::SPKI_DER
12
+ end
13
+ it "raises an error if you don't provide a hash" do
14
+ expect { R509::Spki.new("junk") }.to raise_error(ArgumentError,'Must provide a hash of options')
15
+ end
16
+ it "raises an error if you don't provide spki and subject" do
17
+ expect { R509::Spki.new(:spki => @spki) }.to raise_error(ArgumentError,'Must provide both spki and subject')
18
+ end
19
+ it "raises an error if you don't provide an Array for san_names" do
20
+ expect { R509::Spki.new(:spki => @spki, :subject => [['CN','test']], :san_names => "hello.com") }.to raise_error(ArgumentError,'if san_names are provided they must be in an Array')
21
+ end
22
+ it "loads an RSA spkac" do
23
+ spki = R509::Spki.new( :spki => @spki, :subject => [['CN','spkitest.com']] )
24
+ spki.to_pem.should == @spki
25
+ end
26
+ it "properly strips SPKAC= prefix and loads" do
27
+ spki = R509::Spki.new(
28
+ :spki => "SPKAC="+@spki,
29
+ :subject => [['CN','spkitest.com']]
30
+ )
31
+ spki.to_pem.should == @spki
32
+ end
33
+ it "returns the public key" do
34
+ spki = R509::Spki.new(
35
+ :spki => @spki,
36
+ :subject => [['CN','spkitest.com']]
37
+ )
38
+ spki.public_key.should_not == nil
39
+ end
40
+ it "returns pem" do
41
+ spki = R509::Spki.new(
42
+ :spki => @spki,
43
+ :subject => [['CN','spkitest.com']]
44
+ )
45
+ spki.to_pem.should == @spki
46
+ end
47
+ it "returns der" do
48
+ spki = R509::Spki.new(
49
+ :spki => @spki,
50
+ :subject => [['CN','spkitest.com']]
51
+ )
52
+ spki.to_der.should == @spki_der
53
+ end
54
+ it "writes to pem" do
55
+ spki = R509::Spki.new(
56
+ :spki => @spki,
57
+ :subject => [['CN','spkitest.com']]
58
+ )
59
+ sio = StringIO.new
60
+ sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
61
+ spki.write_pem(sio)
62
+ sio.string.should == @spki
63
+ end
64
+ it "writes to der" do
65
+ spki = R509::Spki.new(
66
+ :spki => @spki,
67
+ :subject => [['CN','spkitest.com']]
68
+ )
69
+ sio = StringIO.new
70
+ sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
71
+ spki.write_der(sio)
72
+ sio.string.should == @spki_der
73
+ end
74
+ it "rsa?" do
75
+ spki = R509::Spki.new(
76
+ :spki => @spki,
77
+ :subject => [['CN','spkitest.com']]
78
+ )
79
+ spki.rsa?.should == true
80
+ spki.dsa?.should == false
81
+ end
82
+ it "returns RSA key algorithm for RSA" do
83
+ spki = R509::Spki.new(
84
+ :spki => @spki,
85
+ :subject => [['CN','spkitest.com']]
86
+ )
87
+ spki.key_algorithm.should == "RSA"
88
+ end
89
+ it "gets RSA bit strength" do
90
+ spki = R509::Spki.new(
91
+ :spki => @spki,
92
+ :subject => [['CN','spkitest.com']]
93
+ )
94
+ spki.bit_strength.should == 2048
95
+ end
96
+ it "loads a DSA spkac" do
97
+ spki = R509::Spki.new(
98
+ :spki => @spki_dsa,
99
+ :subject => [['CN','spkitest.com']]
100
+ )
101
+ spki.to_pem.should == @spki_dsa
102
+ end
103
+ it "gets DSA bit strength" do
104
+ spki = R509::Spki.new(
105
+ :spki => @spki_dsa,
106
+ :subject => [['CN','spkitest.com']]
107
+ )
108
+ spki.bit_strength.should == 2048
109
+ end
110
+ it "dsa?" do
111
+ spki = R509::Spki.new(
112
+ :spki => @spki_dsa,
113
+ :subject => [['CN','spkitest.com']]
114
+ )
115
+ spki.dsa?.should == true
116
+ spki.rsa?.should == false
117
+ end
118
+ it "returns DSA key algorithm for DSA" do
119
+ spki = R509::Spki.new(
120
+ :spki => @spki_dsa,
121
+ :subject => [['CN','spkitest.com']]
122
+ )
123
+ spki.key_algorithm.should == "DSA"
124
+ end
125
+ it "returns expected value for subject" do
126
+ spki = R509::Spki.new(
127
+ :spki => @spki,
128
+ :subject => [['CN','spkitest.com']]
129
+ )
130
+ spki.subject.to_s.should == '/CN=spkitest.com'
131
+ end
132
+ it "returns expected value for san names" do
133
+ spki = R509::Spki.new(
134
+ :spki => @spki,
135
+ :subject => [['CN','spkitest.com']],
136
+ :san_names => ['domain1.com','domain2.com']
137
+ )
138
+ spki.san_names.should == ['domain1.com','domain2.com']
139
+ end
140
+ it "returns empty array when passed no san_names" do
141
+ spki = R509::Spki.new(
142
+ :spki => @spki,
143
+ :subject => [['CN','spkitest.com']]
144
+ )
145
+ spki.san_names.empty?.should == true
146
+ end
147
+ it "creates a valid hash object with to_hash" do
148
+ spki = R509::Spki.new(
149
+ :spki => @spki,
150
+ :subject => [['CN','spkitest.com']],
151
+ :san_names => ["test.local"]
152
+ )
153
+ spki.to_hash[:subject].kind_of?(R509::Subject).should == true
154
+ spki.to_hash[:subject].to_s.should == '/CN=spkitest.com'
155
+ spki.to_hash[:san_names].should == ["test.local"]
156
+ end
157
+ end
@@ -0,0 +1,203 @@
1
+ require 'spec_helper'
2
+ require 'r509/subject'
3
+ require 'openssl'
4
+
5
+ describe R509::Subject do
6
+ before :all do
7
+ @csr_unknown_oid = TestFixtures::CSR_UNKNOWN_OID
8
+ end
9
+
10
+ it "initializes an empty subject and gets the name" do
11
+ subject = R509::Subject.new
12
+ subject.name.to_s.should == ""
13
+ end
14
+ it "initializes an empty subject, adds a field, and gets the name" do
15
+ subject = R509::Subject.new
16
+ subject["CN"] = "domain.com"
17
+ subject.name.to_s.should == "/CN=domain.com"
18
+ end
19
+ it "initializes with a subject array, and gets the name" do
20
+ subject = R509::Subject.new([["CN", "domain.com"], ["O", "my org"]])
21
+ subject.name.to_s.should == "/CN=domain.com/O=my org"
22
+ end
23
+ it "initializes with a name, gets the name" do
24
+ name = OpenSSL::X509::Name.new([["CN", "domain.com"], ["O", "my org"], ["OU", "my unit"]])
25
+ subject = R509::Subject.new(name)
26
+ subject.name.to_s.should == "/CN=domain.com/O=my org/OU=my unit"
27
+ end
28
+ it "initializes with a subject" do
29
+ s1 = R509::Subject.new
30
+ s1["CN"] = "domain.com"
31
+ s1["O"] = "my org"
32
+
33
+ s2 = R509::Subject.new(s1)
34
+ s2.name.to_s.should == s1.name.to_s
35
+ end
36
+ it "preserves order of a full subject line" do
37
+ subject = R509::Subject.new([['CN','langui.sh'],['ST','Illinois'],['L','Chicago'],['C','US'],['emailAddress','ca@langui.sh']])
38
+ subject.name.to_s.should == '/CN=langui.sh/ST=Illinois/L=Chicago/C=US/emailAddress=ca@langui.sh'
39
+ end
40
+ it "preserves order of a full subject line and uses to_s directly" do
41
+ subject = R509::Subject.new([['CN','langui.sh'],['ST','Illinois'],['L','Chicago'],['C','US'],['emailAddress','ca@langui.sh']])
42
+ subject.to_s.should == '/CN=langui.sh/ST=Illinois/L=Chicago/C=US/emailAddress=ca@langui.sh'
43
+ end
44
+ it "preserves order with raw OIDs, and potentially fills in known OID names" do
45
+ subject = R509::Subject.new([['2.5.4.3','common name'],['2.5.4.15','business category'],['2.5.4.7','locality'],['1.3.6.1.4.1.311.60.2.1.3','jurisdiction oid openssl typically does not know']])
46
+ subject.to_s.should == "/CN=common name/businessCategory=business category/L=locality/jurisdictionOfIncorporationCountryName=jurisdiction oid openssl typically does not know"
47
+ end
48
+
49
+ it "edits an existing subject entry" do
50
+ subject = R509::Subject.new([["CN", "domain1.com"], ["O", "my org"]])
51
+ subject.to_s.should == "/CN=domain1.com/O=my org"
52
+
53
+ subject["CN"] = "domain2.com"
54
+ subject.to_s.should == "/CN=domain2.com/O=my org"
55
+ end
56
+
57
+ it "deletes an existing subject entry" do
58
+ subject = R509::Subject.new([["CN", "domain1.com"], ["O", "my org"]])
59
+ subject.to_s.should == "/CN=domain1.com/O=my org"
60
+
61
+ subject.delete("CN")
62
+ subject.to_s.should == "/O=my org"
63
+ end
64
+
65
+ it "is empty when initialized" do
66
+ subject = R509::Subject.new
67
+ subject.empty?.should == true
68
+ subject["CN"] = "domain.com"
69
+ subject.empty?.should == false
70
+ end
71
+
72
+ it "is not empty" do
73
+ subject = R509::Subject.new([["CN", "domain1.com"]])
74
+ subject.empty?.should == false
75
+ end
76
+
77
+ it "can get a component out of the subject" do
78
+ subject = R509::Subject.new([["CN", "domain.com"]])
79
+ subject["CN"].should == "domain.com"
80
+ subject["O"].should == nil
81
+ end
82
+
83
+ it "adds an OID" do
84
+ subject = R509::Subject.new
85
+ subject['1.3.6.1.4.1.311.60.2.1.3'] = 'jurisdiction oid openssl typically does not know'
86
+ subject['1.3.6.1.4.1.311.60.2.1.3'].should == 'jurisdiction oid openssl typically does not know'
87
+ end
88
+
89
+ it "deletes an OID" do
90
+ subject = R509::Subject.new([["CN", "domain.com"], ['1.3.6.1.4.1.38383.60.2.1.0.0', 'random oid']])
91
+ subject.to_s.should == "/CN=domain.com/1.3.6.1.4.1.38383.60.2.1.0.0=random oid"
92
+ subject.delete("1.3.6.1.4.1.38383.60.2.1.0.0")
93
+ subject.to_s.should == "/CN=domain.com"
94
+ end
95
+
96
+ it "fails when you instantiate with an unknown shortname" do
97
+ expect { R509::Subject.new([["NOTRIGHT", "foo"]]) }.to raise_error(OpenSSL::X509::NameError)
98
+ end
99
+
100
+ it "fails when you add an unknown shortname" do
101
+ subject = R509::Subject.new
102
+ expect { subject["WRONG"] = "bar" }.to raise_error(OpenSSL::X509::NameError)
103
+ end
104
+
105
+ it "parses unknown OIDs out of a CSR" do
106
+ csr = R509::Csr.new(:csr => @csr_unknown_oid)
107
+ subject = R509::Subject.new(csr.subject)
108
+ subject["1.2.3.4.5.6.7.8.9.8.7.6.5.4.3.2.1.0.0"].should == "random oid!"
109
+ subject["1.3.3.543.567.32.43.335.1.1.1"].should == "another random oid!"
110
+ subject["CN"].should == 'normaldomain.com'
111
+ end
112
+
113
+ end
114
+
115
+ describe R509::NameSanitizer do
116
+ before :all do
117
+ @sanitizer = R509::NameSanitizer.new
118
+ end
119
+
120
+ it "when it has only known OIDs" do
121
+ name = OpenSSL::X509::Name.new [["C", "US"], ["ST", "Illinois"]]
122
+ array = @sanitizer.sanitize(name)
123
+ array.size.should == 2
124
+ array[0][0].should == "C"
125
+ array[0][1].should == "US"
126
+ array[1][0].should == "ST"
127
+ array[1][1].should == "Illinois"
128
+ end
129
+
130
+ it "when it has only unknown OIDs" do
131
+ name = OpenSSL::X509::Name.new [["1.2.3.4", "US"], ["1.2.3.5", "Illinois"]]
132
+ array = @sanitizer.sanitize(name)
133
+ array.size.should == 2
134
+ array[0][0].should == "1.2.3.4"
135
+ array[0][1].should == "US"
136
+ array[1][0].should == "1.2.3.5"
137
+ array[1][1].should == "Illinois"
138
+ end
139
+
140
+ it "when it has an unknown between two knowns" do
141
+ name = OpenSSL::X509::Name.new [["CN", "domain.com"], ["1.2.3.4", "US"], ["ST", "Illinois"]]
142
+ array = @sanitizer.sanitize(name)
143
+ array.size.should == 3
144
+ array[0][0].should == "CN"
145
+ array[0][1].should == "domain.com"
146
+ array[1][0].should == "1.2.3.4"
147
+ array[1][1].should == "US"
148
+ array[2][0].should == "ST"
149
+ array[2][1].should == "Illinois"
150
+ end
151
+
152
+ it "when it has a known between two unknowns" do
153
+ name = OpenSSL::X509::Name.new [["1.2.3.4", "domain.com"], ["C", "US"], ["1.2.3.5", "Illinois"]]
154
+ array = @sanitizer.sanitize(name)
155
+ array.size.should == 3
156
+ array[0][0].should == "1.2.3.4"
157
+ array[0][1].should == "domain.com"
158
+ array[1][0].should == "C"
159
+ array[1][1].should == "US"
160
+ array[2][0].should == "1.2.3.5"
161
+ array[2][1].should == "Illinois"
162
+ end
163
+
164
+ it "when a known has the same value as an unknown defined before it" do
165
+ name = OpenSSL::X509::Name.new [["1.2.3.4", "domain.com"], ["CN", "domain.com"]]
166
+ array = @sanitizer.sanitize(name)
167
+ array.size.should == 2
168
+ array[0][0].should == "1.2.3.4"
169
+ array[0][1].should == "domain.com"
170
+ array[1][0].should == "CN"
171
+ array[1][1].should == "domain.com"
172
+ end
173
+
174
+ it "when two unknowns have the same value" do
175
+ name = OpenSSL::X509::Name.new [["1.2.3.4", "domain.com"], ["1.2.3.5", "domain.com"]]
176
+ array = @sanitizer.sanitize(name)
177
+ array.size.should == 2
178
+ array[0][0].should == "1.2.3.4"
179
+ array[0][1].should == "domain.com"
180
+ array[1][0].should == "1.2.3.5"
181
+ array[1][1].should == "domain.com"
182
+ end
183
+
184
+ it "when two unknowns have the same oid and different values" do
185
+ name = OpenSSL::X509::Name.new [["1.2.3.4", "domain.com"], ["1.2.3.4", "other"]]
186
+ array = @sanitizer.sanitize(name)
187
+ array.size.should == 2
188
+ array[0][0].should == "1.2.3.4"
189
+ array[0][1].should == "domain.com"
190
+ array[1][0].should == "1.2.3.4"
191
+ array[1][1].should == "other"
192
+ end
193
+
194
+ it "when two unknowns have the same oid and the same value" do
195
+ name = OpenSSL::X509::Name.new [["1.2.3.4", "domain.com"], ["1.2.3.4", "domain.com"]]
196
+ array = @sanitizer.sanitize(name)
197
+ array.size.should == 2
198
+ array[0][0].should == "1.2.3.4"
199
+ array[0][1].should == "domain.com"
200
+ array[1][0].should == "1.2.3.4"
201
+ array[1][1].should == "domain.com"
202
+ end
203
+ end
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+ require 'r509/validity'
3
+ require 'openssl'
4
+
5
+ describe R509::Validity do
6
+ context "status" do
7
+ it "has no status" do
8
+ status = R509::Validity::Status.new
9
+ status.status.should == nil
10
+ status.ocsp_status.should == OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
11
+ end
12
+ it "has a valid status" do
13
+ status = R509::Validity::Status.new(:status => R509::Validity::VALID)
14
+ status.status.should == R509::Validity::VALID
15
+ status.ocsp_status.should == OpenSSL::OCSP::V_CERTSTATUS_GOOD
16
+ end
17
+ it "has a revoked status" do
18
+ status = R509::Validity::Status.new(:status => R509::Validity::REVOKED)
19
+ status.status.should == R509::Validity::REVOKED
20
+ status.ocsp_status.should == OpenSSL::OCSP::V_CERTSTATUS_REVOKED
21
+ status.revocation_time.should_not == nil
22
+ status.revocation_reason.should == 0
23
+ end
24
+ it "has an unknown status" do
25
+ status = R509::Validity::Status.new(:status => R509::Validity::UNKNOWN)
26
+ status.status.should == R509::Validity::UNKNOWN
27
+ status.ocsp_status.should == OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
28
+ end
29
+ it "has some other status that we don't know about" do
30
+ status = R509::Validity::Status.new(:status => 10101010101)
31
+ status.status.should == 10101010101
32
+ status.ocsp_status.should == OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
33
+ end
34
+ it "has no revocation time or reason specified (and isn't revoked)" do
35
+ status = R509::Validity::Status.new
36
+ status.revocation_time.should == nil
37
+ status.revocation_reason.should == 0
38
+ end
39
+ it "specifies a revocation time" do
40
+ time = Time.now.to_i
41
+ status = R509::Validity::Status.new(:revocation_time => time)
42
+ status.revocation_time.should == time
43
+ end
44
+ it "specifies a revocation reason" do
45
+ status = R509::Validity::Status.new(:revocation_reason => 2)
46
+ status.revocation_reason.should == 2
47
+ end
48
+ end
49
+ context "writer base" do
50
+ it "calls issue" do
51
+ writer = R509::Validity::Writer.new
52
+ expect { writer.issue("a",1) }.to raise_error(NotImplementedError, "You must call #issue on a subclass of Writer")
53
+ end
54
+ it "calls revoke" do
55
+ writer = R509::Validity::Writer.new
56
+ expect { writer.revoke("a",1, 1) }.to raise_error(NotImplementedError, "You must call #revoke on a subclass of Writer")
57
+ end
58
+ it "calls is_available?" do
59
+ writer = R509::Validity::Writer.new
60
+ expect { writer.is_available? }.to raise_error(NotImplementedError, "You must call #is_available? on a subclass of Writer")
61
+ end
62
+ end
63
+ context "checker base" do
64
+ it "calls check" do
65
+ checker = R509::Validity::Checker.new
66
+ expect { checker.check("a",1) }.to raise_error(NotImplementedError, "You must call #check on a subclass of Checker")
67
+ end
68
+ it "calls is_available?" do
69
+ checker = R509::Validity::Checker.new
70
+ expect { checker.is_available? }.to raise_error(NotImplementedError, "You must call #is_available? on a subclass of Checker")
71
+ end
72
+ end
73
+ context "writer default" do
74
+ it "calls issue" do
75
+ writer = R509::Validity::DefaultWriter.new
76
+ writer.issue("a",1)
77
+ end
78
+ it "calls revoke" do
79
+ writer = R509::Validity::DefaultWriter.new
80
+ writer.revoke("a",1, 1)
81
+ end
82
+ it "calls is_available?" do
83
+ writer = R509::Validity::DefaultWriter.new
84
+ writer.is_available?.should == true
85
+ end
86
+ end
87
+ context "checker default" do
88
+ it "calls check" do
89
+ checker = R509::Validity::DefaultChecker.new
90
+ status = checker.check("a",1)
91
+ status.status.should == R509::Validity::VALID
92
+ end
93
+ it "calls is_available?" do
94
+ checker = R509::Validity::DefaultChecker.new
95
+ checker.is_available?.should == true
96
+ end
97
+ end
98
+ end