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.
- data/README.md +447 -0
- data/Rakefile +38 -0
- data/bin/r509 +96 -0
- data/bin/r509-parse +35 -0
- data/doc/R509.html +154 -0
- data/doc/R509/Cert.html +3954 -0
- data/doc/R509/Cert/Extensions.html +360 -0
- data/doc/R509/Cert/Extensions/AuthorityInfoAccess.html +391 -0
- data/doc/R509/Cert/Extensions/AuthorityKeyIdentifier.html +148 -0
- data/doc/R509/Cert/Extensions/BasicConstraints.html +482 -0
- data/doc/R509/Cert/Extensions/CrlDistributionPoints.html +316 -0
- data/doc/R509/Cert/Extensions/ExtendedKeyUsage.html +780 -0
- data/doc/R509/Cert/Extensions/KeyUsage.html +1230 -0
- data/doc/R509/Cert/Extensions/SubjectAlternativeName.html +467 -0
- data/doc/R509/Cert/Extensions/SubjectKeyIdentifier.html +216 -0
- data/doc/R509/CertificateAuthority.html +126 -0
- data/doc/R509/CertificateAuthority/Signer.html +855 -0
- data/doc/R509/Config.html +127 -0
- data/doc/R509/Config/CaConfig.html +2144 -0
- data/doc/R509/Config/CaConfigPool.html +599 -0
- data/doc/R509/Config/CaProfile.html +656 -0
- data/doc/R509/Config/SubjectItemPolicy.html +578 -0
- data/doc/R509/Crl.html +126 -0
- data/doc/R509/Crl/Administrator.html +2077 -0
- data/doc/R509/Crl/Parser.html +1224 -0
- data/doc/R509/Csr.html +2248 -0
- data/doc/R509/IOHelpers.html +564 -0
- data/doc/R509/MessageDigest.html +396 -0
- data/doc/R509/NameSanitizer.html +319 -0
- data/doc/R509/Ocsp.html +128 -0
- data/doc/R509/Ocsp/Request.html +126 -0
- data/doc/R509/Ocsp/Request/Nonce.html +160 -0
- data/doc/R509/Ocsp/Response.html +837 -0
- data/doc/R509/OidMapper.html +393 -0
- data/doc/R509/PrivateKey.html +1647 -0
- data/doc/R509/R509Error.html +134 -0
- data/doc/R509/Spki.html +1424 -0
- data/doc/R509/Subject.html +836 -0
- data/doc/R509/Validity.html +160 -0
- data/doc/R509/Validity/Checker.html +320 -0
- data/doc/R509/Validity/DefaultChecker.html +283 -0
- data/doc/R509/Validity/DefaultWriter.html +330 -0
- data/doc/R509/Validity/Status.html +561 -0
- data/doc/R509/Validity/Writer.html +394 -0
- data/doc/_index.html +501 -0
- data/doc/class_list.html +53 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +328 -0
- data/doc/file.README.html +534 -0
- data/doc/file.r509.html +149 -0
- data/doc/file_list.html +58 -0
- data/doc/frames.html +28 -0
- data/doc/index.html +534 -0
- data/doc/js/app.js +208 -0
- data/doc/js/full_list.js +173 -0
- data/doc/js/jquery.js +4 -0
- data/doc/methods_list.html +1932 -0
- data/doc/top-level-namespace.html +112 -0
- data/lib/r509.rb +22 -0
- data/lib/r509/cert.rb +414 -0
- data/lib/r509/cert/extensions.rb +309 -0
- data/lib/r509/certificateauthority.rb +290 -0
- data/lib/r509/config.rb +407 -0
- data/lib/r509/crl.rb +379 -0
- data/lib/r509/csr.rb +324 -0
- data/lib/r509/exceptions.rb +5 -0
- data/lib/r509/io_helpers.rb +52 -0
- data/lib/r509/messagedigest.rb +49 -0
- data/lib/r509/ocsp.rb +85 -0
- data/lib/r509/oidmapper.rb +32 -0
- data/lib/r509/privatekey.rb +185 -0
- data/lib/r509/spki.rb +112 -0
- data/lib/r509/subject.rb +133 -0
- data/lib/r509/validity.rb +92 -0
- data/lib/r509/version.rb +4 -0
- data/r509.yaml +73 -0
- data/spec/cert/extensions_spec.rb +632 -0
- data/spec/cert_spec.rb +321 -0
- data/spec/certificate_authority_spec.rb +260 -0
- data/spec/config_spec.rb +349 -0
- data/spec/crl_spec.rb +215 -0
- data/spec/csr_spec.rb +302 -0
- data/spec/fixtures.rb +233 -0
- data/spec/fixtures/cert1.der +0 -0
- data/spec/fixtures/cert1.pem +24 -0
- data/spec/fixtures/cert1_public_key_modulus.txt +1 -0
- data/spec/fixtures/cert3.p12 +0 -0
- data/spec/fixtures/cert3.pem +28 -0
- data/spec/fixtures/cert3_key.pem +27 -0
- data/spec/fixtures/cert3_key_des3.pem +30 -0
- data/spec/fixtures/cert4.pem +14 -0
- data/spec/fixtures/cert5.pem +30 -0
- data/spec/fixtures/cert6.pem +26 -0
- data/spec/fixtures/cert_expired.pem +26 -0
- data/spec/fixtures/cert_not_yet_valid.pem +26 -0
- data/spec/fixtures/cert_san.pem +27 -0
- data/spec/fixtures/cert_san2.pem +22 -0
- data/spec/fixtures/config_pool_test_minimal.yaml +15 -0
- data/spec/fixtures/config_test.yaml +41 -0
- data/spec/fixtures/config_test_engine_key.yaml +7 -0
- data/spec/fixtures/config_test_engine_no_key_name.yaml +6 -0
- data/spec/fixtures/config_test_minimal.yaml +7 -0
- data/spec/fixtures/config_test_password.yaml +7 -0
- data/spec/fixtures/config_test_various.yaml +100 -0
- data/spec/fixtures/crl_list_file.txt +1 -0
- data/spec/fixtures/crl_with_reason.pem +17 -0
- data/spec/fixtures/csr1.der +0 -0
- data/spec/fixtures/csr1.pem +17 -0
- data/spec/fixtures/csr1_key.der +0 -0
- data/spec/fixtures/csr1_key.pem +27 -0
- data/spec/fixtures/csr1_key_encrypted_des3.pem +30 -0
- data/spec/fixtures/csr1_newlines.pem +32 -0
- data/spec/fixtures/csr1_no_begin_end.pem +15 -0
- data/spec/fixtures/csr1_public_key_modulus.txt +1 -0
- data/spec/fixtures/csr2.pem +15 -0
- data/spec/fixtures/csr2_key.pem +27 -0
- data/spec/fixtures/csr3.pem +16 -0
- data/spec/fixtures/csr4.pem +25 -0
- data/spec/fixtures/csr_dsa.pem +15 -0
- data/spec/fixtures/csr_invalid_signature.pem +13 -0
- data/spec/fixtures/dsa_key.pem +20 -0
- data/spec/fixtures/key4.pem +27 -0
- data/spec/fixtures/key4_encrypted_des3.pem +30 -0
- data/spec/fixtures/missing_key_identifier_ca.cer +21 -0
- data/spec/fixtures/missing_key_identifier_ca.key +27 -0
- data/spec/fixtures/ocsptest.r509.local.pem +27 -0
- data/spec/fixtures/ocsptest.r509.local_ocsp_request.der +0 -0
- data/spec/fixtures/ocsptest2.r509.local.pem +27 -0
- data/spec/fixtures/second_ca.cer +26 -0
- data/spec/fixtures/second_ca.key +27 -0
- data/spec/fixtures/spkac.der +0 -0
- data/spec/fixtures/spkac.txt +1 -0
- data/spec/fixtures/spkac_dsa.txt +1 -0
- data/spec/fixtures/stca.pem +22 -0
- data/spec/fixtures/stca_ocsp_request.der +0 -0
- data/spec/fixtures/stca_ocsp_response.der +0 -0
- data/spec/fixtures/test1.csr +17 -0
- data/spec/fixtures/test_ca.cer +22 -0
- data/spec/fixtures/test_ca.key +28 -0
- data/spec/fixtures/test_ca.p12 +0 -0
- data/spec/fixtures/test_ca_des3.key +30 -0
- data/spec/fixtures/test_ca_ocsp.cer +26 -0
- data/spec/fixtures/test_ca_ocsp.key +27 -0
- data/spec/fixtures/test_ca_ocsp.p12 +0 -0
- data/spec/fixtures/test_ca_ocsp_chain.txt +48 -0
- data/spec/fixtures/test_ca_ocsp_response.der +0 -0
- data/spec/fixtures/test_ca_subroot.cer +26 -0
- data/spec/fixtures/test_ca_subroot.key +27 -0
- data/spec/fixtures/test_ca_subroot_ocsp.cer +25 -0
- data/spec/fixtures/test_ca_subroot_ocsp.key +27 -0
- data/spec/fixtures/test_ca_subroot_ocsp_response.der +0 -0
- data/spec/fixtures/unknown_oid.csr +17 -0
- data/spec/message_digest_spec.rb +89 -0
- data/spec/ocsp_spec.rb +111 -0
- data/spec/oid_mapper_spec.rb +31 -0
- data/spec/privatekey_spec.rb +198 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/spki_spec.rb +157 -0
- data/spec/subject_spec.rb +203 -0
- data/spec/validity_spec.rb +98 -0
- metadata +257 -0
data/spec/spec_helper.rb
ADDED
|
@@ -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
|