r509-ocsp-responder 0.3.1 → 0.3.2

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/spec/fixtures.rb CHANGED
@@ -3,194 +3,149 @@ require 'pathname'
3
3
  require 'r509/io_helpers'
4
4
 
5
5
  module TestFixtures
6
- extend R509::IOHelpers
7
-
8
- FIXTURES_PATH = Pathname.new(__FILE__).dirname + "fixtures"
9
-
10
- def self.read_fixture(filename)
11
- read_data((FIXTURES_PATH + filename).to_s)
12
- end
13
-
14
- #Trustwave cert for langui.sh
15
- CERT = read_fixture('cert1.pem')
16
-
17
- #Trustwave root cert
18
- STCA_CERT = read_fixture('stca.pem')
19
-
20
-
21
- TEST_CA_CERT = read_fixture('test_ca.cer')
22
- TEST_CA_KEY = read_fixture('test_ca.key')
23
-
24
- TEST_CA_OCSP_CERT = read_fixture('test_ca_ocsp.cer')
25
- TEST_CA_OCSP_KEY = read_fixture('test_ca_ocsp.key')
26
-
27
- TEST_CA_SUBROOT_CERT = read_fixture('test_ca_subroot.cer')
28
- TEST_CA_SUBROOT_KEY = read_fixture('test_ca_subroot.key')
29
-
30
- TEST_CA_SUBROOT_OCSP_CERT = read_fixture('test_ca_subroot_ocsp.cer')
31
- TEST_CA_SUBROOT_OCSP_KEY = read_fixture('test_ca_subroot_ocsp.key')
32
-
33
- SECOND_CA_CERT = read_fixture('second_ca.cer')
34
- SECOND_CA_KEY = read_fixture('second_ca.key')
35
-
36
- OCSP_TEST_CERT = read_fixture('ocsptest.r509.local.pem')
37
-
38
- STCA_OCSP_REQUEST = read_fixture('stca_ocsp_request.der')
39
- STCA_OCSP_RESPONSE = read_fixture('stca_ocsp_response.der')
40
-
41
- def self.test_ca_cert
42
- R509::Cert.new(:cert => TEST_CA_CERT, :key => TEST_CA_KEY)
43
- end
44
-
45
- def self.test_ca_subroot_cert
46
- R509::Cert.new(:cert => TEST_CA_SUBROOT_CERT, :key => TEST_CA_SUBROOT_KEY)
47
- end
48
-
49
- def self.test_ca_server_profile
50
- R509::Config::CaProfile.new(
51
- :basic_constraints => "CA:FALSE",
52
- :key_usage => ["digitalSignature","keyEncipherment"],
53
- :extended_key_usage => ["serverAuth"],
54
- :certificate_policies => [
55
- [
56
- "policyIdentifier=2.16.840.1.12345.1.2.3.4.1",
57
- "CPS.1=http://example.com/cps"
58
- ]
59
- ]
60
- )
61
-
62
- end
63
-
64
- def self.test_ca_server_profile_with_subject_item_policy
65
- subject_item_policy = R509::Config::SubjectItemPolicy.new(
66
- "CN" => "required",
67
- "O" => "optional",
68
- "ST" => "required",
69
- "C" => "required",
70
- "OU" => "optional"
71
- )
72
- R509::Config::CaProfile.new(
73
- :basic_constraints => "CA:FALSE",
74
- :key_usage => ["digitalSignature","keyEncipherment"],
75
- :extended_key_usage => ["serverAuth"],
76
- :certificate_policies => [
77
- [
78
- "policyIdentifier=2.16.840.1.12345.1.2.3.4.1",
79
- "CPS.1=http://example.com/cps"
80
- ]
81
- ],
82
- :subject_item_policy => subject_item_policy
83
- )
84
- end
85
-
86
- def self.test_ca_subroot_profile
87
- R509::Config::CaProfile.new(
88
- :basic_constraints => "CA:TRUE,pathlen:0",
89
- :key_usage => ["keyCertSign","cRLSign"],
90
- :extended_key_usage => [],
91
- :certificate_policies => nil)
92
- end
93
-
94
- def self.test_ca_ocspsigner_profile
95
- R509::Config::CaProfile.new(
96
- :basic_constraints => "CA:FALSE",
97
- :key_usage => ["digitalSignature"],
98
- :extended_key_usage => ["OCSPSigning"],
99
- :certificate_policies => nil)
100
- end
101
-
102
- def self.second_ca_cert
103
- R509::Cert.new(:cert => SECOND_CA_CERT, :key => SECOND_CA_KEY)
104
- end
105
-
106
- def self.second_ca_server_profile
107
- R509::Config::CaProfile.new(
108
- :basic_constraints => "CA:FALSE",
109
- :key_usage => ["digitalSignature","keyEncipherment"],
110
- :extended_key_usage => ["serverAuth"],
111
- :certificate_policies => [
112
- [
113
- "policyIdentifier=2.16.840.1.12345.1.2.3.4.1",
114
- "CPS.1=http://example.com/cps"
115
- ]
116
- ]
117
- )
118
-
119
- end
120
-
121
- def self.second_ca_subroot_profile
122
- R509::Config::CaProfile.new(
123
- :basic_constraints => "CA:TRUE,pathlen:0",
124
- :key_usage => ["keyCertSign","cRLSign"],
125
- :extended_key_usage => [],
126
- :certificate_policies => nil)
127
- end
128
-
129
-
130
- # @return [R509::Config::CaConfig]
131
- def self.test_ca_config
132
- crl_list_sio = StringIO.new
133
- crl_list_sio.set_encoding("BINARY") if crl_list_sio.respond_to?(:set_encoding)
134
- crl_number_sio = StringIO.new
135
- crl_number_sio.set_encoding("BINARY") if crl_number_sio.respond_to?(:set_encoding)
136
-
137
- opts = {
138
- :ca_cert => test_ca_cert(),
139
- :cdp_location => 'URI:http://crl.domain.com/test_ca.crl',
140
- :ocsp_location => 'URI:http://ocsp.domain.com',
141
- :ocsp_start_skew_seconds => 3600,
142
- :ocsp_validity_hours => 48,
143
- :crl_list_file => crl_list_sio,
144
- :crl_number_file => crl_number_sio
145
- }
146
- ret = R509::Config::CaConfig.new(opts)
147
-
148
- ret.set_profile("server", self.test_ca_server_profile)
149
- ret.set_profile("subroot", self.test_ca_subroot_profile)
150
- ret.set_profile("ocspsigner", self.test_ca_ocspsigner_profile)
151
- ret.set_profile("server_with_subject_item_policy", self.test_ca_server_profile_with_subject_item_policy)
152
-
153
- ret
154
- end
155
-
156
- # @return [R509::Config::CaConfig]
157
- def self.test_ca_subroot_config
158
- crl_list_sio = StringIO.new
159
- crl_list_sio.set_encoding("BINARY") if crl_list_sio.respond_to?(:set_encoding)
160
- crl_number_sio = StringIO.new
161
- crl_number_sio.set_encoding("BINARY") if crl_number_sio.respond_to?(:set_encoding)
162
-
163
- opts = {
164
- :ca_cert => test_ca_subroot_cert(),
165
- :cdp_location => 'URI:http://crl.domain.com/test_ca.crl',
166
- :ocsp_location => 'URI:http://ocsp.domain.com',
167
- :ocsp_start_skew_seconds => 3600,
168
- :ocsp_validity_hours => 48,
169
- :crl_list_file => crl_list_sio,
170
- :crl_number_file => crl_number_sio
171
- }
172
- ret = R509::Config::CaConfig.new(opts)
173
-
174
- ret.set_profile("server", self.test_ca_server_profile)
175
- ret.set_profile("subroot", self.test_ca_subroot_profile)
176
- ret.set_profile("ocspsigner", self.test_ca_ocspsigner_profile)
177
- ret.set_profile("server_with_subject_item_policy", self.test_ca_server_profile_with_subject_item_policy)
178
-
179
- ret
180
- end
181
-
182
- # @return [R509::Config::CaConfig] secondary config
183
- def self.second_ca_config
184
- opts = {
185
- :ca_cert => second_ca_cert(),
186
- :cdp_location => 'URI:http://crl.domain.com/test_ca.crl',
187
- :ocsp_location => 'URI:http://ocsp.domain.com'
188
- }
189
- ret = R509::Config::CaConfig.new(opts)
190
-
191
- ret.set_profile("server", self.second_ca_server_profile)
192
- ret.set_profile("subroot", self.second_ca_subroot_profile)
193
-
194
- ret
195
- end
6
+ extend R509::IOHelpers
7
+
8
+ FIXTURES_PATH = Pathname.new(__FILE__).dirname + "fixtures"
9
+
10
+ def self.read_fixture(filename)
11
+ read_data((FIXTURES_PATH + filename).to_s)
12
+ end
13
+
14
+ #Trustwave cert for langui.sh
15
+ CERT = read_fixture('cert1.pem')
16
+
17
+ #Trustwave root cert
18
+ STCA_CERT = read_fixture('stca.pem')
19
+
20
+
21
+ TEST_CA_CERT = read_fixture('test_ca.cer')
22
+ TEST_CA_KEY = read_fixture('test_ca.key')
23
+
24
+ TEST_CA_OCSP_CERT = read_fixture('test_ca_ocsp.cer')
25
+ TEST_CA_OCSP_KEY = read_fixture('test_ca_ocsp.key')
26
+
27
+ TEST_CA_SUBROOT_CERT = read_fixture('test_ca_subroot.cer')
28
+ TEST_CA_SUBROOT_KEY = read_fixture('test_ca_subroot.key')
29
+
30
+ TEST_CA_SUBROOT_OCSP_CERT = read_fixture('test_ca_subroot_ocsp.cer')
31
+ TEST_CA_SUBROOT_OCSP_KEY = read_fixture('test_ca_subroot_ocsp.key')
32
+
33
+ SECOND_CA_CERT = read_fixture('second_ca.cer')
34
+ SECOND_CA_KEY = read_fixture('second_ca.key')
35
+
36
+ OCSP_TEST_CERT = read_fixture('ocsptest.r509.local.pem')
37
+
38
+ STCA_OCSP_REQUEST = read_fixture('stca_ocsp_request.der')
39
+ STCA_OCSP_RESPONSE = read_fixture('stca_ocsp_response.der')
40
+
41
+ TEST_CA_EC_CERT = read_fixture('test_ca_ec.cer')
42
+ TEST_CA_EC_KEY = read_fixture('test_ca_ec.key')
43
+
44
+ def self.test_ca_cert
45
+ R509::Cert.new(:cert => TEST_CA_CERT, :key => TEST_CA_KEY)
46
+ end
47
+
48
+ def self.test_ca_ec_cert
49
+ R509::Cert.new(:cert => TEST_CA_EC_CERT, :key => TEST_CA_EC_KEY)
50
+ end
51
+
52
+ def self.test_ca_subroot_cert
53
+ R509::Cert.new(:cert => TEST_CA_SUBROOT_CERT, :key => TEST_CA_SUBROOT_KEY)
54
+ end
55
+
56
+ def self.test_ca_server_profile
57
+ R509::Config::CAProfile.new(
58
+ :basic_constraints => { "ca" => false },
59
+ :key_usage => ["digitalSignature","keyEncipherment"],
60
+ :extended_key_usage => ["serverAuth"]
61
+ )
62
+
63
+ end
64
+
65
+ def self.second_ca_cert
66
+ R509::Cert.new(:cert => SECOND_CA_CERT, :key => SECOND_CA_KEY)
67
+ end
68
+
69
+ def self.second_ca_server_profile
70
+ R509::Config::CAProfile.new(
71
+ :basic_constraints => { "ca" => false },
72
+ :key_usage => ["digitalSignature","keyEncipherment"],
73
+ :extended_key_usage => ["serverAuth"]
74
+ )
75
+
76
+ end
77
+
78
+ # @return [R509::Config::CAConfig]
79
+ def self.test_ca_config
80
+ crl_list_sio = StringIO.new
81
+ crl_list_sio.set_encoding("BINARY") if crl_list_sio.respond_to?(:set_encoding)
82
+ crl_number_sio = StringIO.new
83
+ crl_number_sio.set_encoding("BINARY") if crl_number_sio.respond_to?(:set_encoding)
84
+
85
+ opts = {
86
+ :ca_cert => test_ca_cert(),
87
+ :ocsp_start_skew_seconds => 3600,
88
+ :ocsp_validity_hours => 48,
89
+ :crl_list_file => crl_list_sio,
90
+ :crl_number_file => crl_number_sio
91
+ }
92
+ ret = R509::Config::CAConfig.new(opts)
93
+
94
+ ret.set_profile("server", self.test_ca_server_profile)
95
+
96
+ ret
97
+ end
98
+
99
+ # @return [R509::Config::CAConfig]
100
+ def self.test_ca_ec_config
101
+ crl_list_sio = StringIO.new
102
+ crl_list_sio.set_encoding("BINARY") if crl_list_sio.respond_to?(:set_encoding)
103
+ crl_number_sio = StringIO.new
104
+ crl_number_sio.set_encoding("BINARY") if crl_number_sio.respond_to?(:set_encoding)
105
+
106
+ opts = {
107
+ :ca_cert => test_ca_ec_cert(),
108
+ :ocsp_start_skew_seconds => 3600,
109
+ :ocsp_validity_hours => 48,
110
+ :crl_list_file => crl_list_sio,
111
+ :crl_number_file => crl_number_sio
112
+ }
113
+ ret = R509::Config::CAConfig.new(opts)
114
+
115
+ ret.set_profile("server", self.test_ca_server_profile)
116
+ ret
117
+ end
118
+
119
+ # @return [R509::Config::CAConfig]
120
+ def self.test_ca_subroot_config
121
+ crl_list_sio = StringIO.new
122
+ crl_list_sio.set_encoding("BINARY") if crl_list_sio.respond_to?(:set_encoding)
123
+ crl_number_sio = StringIO.new
124
+ crl_number_sio.set_encoding("BINARY") if crl_number_sio.respond_to?(:set_encoding)
125
+
126
+ opts = {
127
+ :ca_cert => test_ca_subroot_cert(),
128
+ :ocsp_start_skew_seconds => 3600,
129
+ :ocsp_validity_hours => 48,
130
+ :crl_list_file => crl_list_sio,
131
+ :crl_number_file => crl_number_sio
132
+ }
133
+ ret = R509::Config::CAConfig.new(opts)
134
+
135
+ ret.set_profile("server", self.test_ca_server_profile)
136
+
137
+ ret
138
+ end
139
+
140
+ # @return [R509::Config::CAConfig] secondary config
141
+ def self.second_ca_config
142
+ opts = {
143
+ :ca_cert => second_ca_cert(),
144
+ }
145
+ ret = R509::Config::CAConfig.new(opts)
146
+
147
+ ret.set_profile("server", self.second_ca_server_profile)
148
+
149
+ ret
150
+ end
196
151
  end
@@ -0,0 +1,14 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIICJzCCAaygAwIBAgITBhgGAz3nZpKHtz6KQjnGF3l8IzAKBggqhkjOPQQDAjBb
3
+ MQswCQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNh
4
+ Z28xETAPBgNVBAoMCHI1MDkgTExDMRQwEgYDVQQDDAtyNTA5IEVDQyBDQTAeFw0x
5
+ MzAxMjMxNDE1MjBaFw0zMzAxMTgyMDE1MjBaMFsxCzAJBgNVBAYTAlVTMREwDwYD
6
+ VQQIDAhJbGxpbm9pczEQMA4GA1UEBwwHQ2hpY2FnbzERMA8GA1UECgwIcjUwOSBM
7
+ TEMxFDASBgNVBAMMC3I1MDkgRUNDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE
8
+ FoGSwxFhGtPcBRnmKSwVnYRhniE86GmTTCGyb02ch5ZENzmjdTuR4MoeBmG5RXzH
9
+ mX1I6rcFW5sJWnmOncE0zcl7qGxash/+3wFm3qwwR1YUpDZ+TeYtezqkEegN+I2T
10
+ ozIwMDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS27qtirnzRTXfTrJOA46dI
11
+ r1hc4jAKBggqhkjOPQQDAgNpADBmAjEAgy6c00RdXZ5wmRo5uFOu9aa5kUJo912+
12
+ hiHmddmFVCyQcvsX+hq2GvFKLhwxty9jAjEA4e4WY48QArCidovB/iYXRkvE5efL
13
+ oqXZOHh/QzwiNz66ZIGR8tv2iLoRXoG4fiWG
14
+ -----END CERTIFICATE-----
@@ -0,0 +1,6 @@
1
+ -----BEGIN EC PRIVATE KEY-----
2
+ MIGkAgEBBDCVvOkiIED5VN04e0/zOjv2UHZ94vRt4NP939/UnPkxxoy8yQRCDW9v
3
+ vJp4kJ2uz12gBwYFK4EEACKhZANiAAQWgZLDEWEa09wFGeYpLBWdhGGeITzoaZNM
4
+ IbJvTZyHlkQ3OaN1O5Hgyh4GYblFfMeZfUjqtwVbmwlaeY6dwTTNyXuobFqyH/7f
5
+ AWberDBHVhSkNn5N5i17OqQR6A34jZM=
6
+ -----END EC PRIVATE KEY-----
data/spec/server_spec.rb CHANGED
@@ -1,400 +1,408 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper'
2
2
  require 'time'
3
-
4
-
5
- describe R509::Ocsp::Responder::Server do
6
- before :all do
7
- @test_ca_cert = OpenSSL::X509::Certificate.new(File.read(Pathname.new(__FILE__).dirname + "fixtures/test_ca.cer"))
8
- @second_ca_cert = OpenSSL::X509::Certificate.new(File.read(Pathname.new(__FILE__).dirname + "fixtures/second_ca.cer"))
9
- end
10
-
11
- before :each do
12
- # clear the dependo before each test
13
- Dependo::Registry.clear
14
- Dependo::Registry[:log] = Logger.new(nil)
15
-
16
- # we always want to mock with a new redis
17
- @redis = double("redis")
18
- Dependo::Registry[:redis] = @redis
19
-
20
- # and we want to mock the stats recorder
21
- @stats = double("stats")
22
- Dependo::Registry[:stats] = @stats
23
-
24
- # default value for :copy_nonce is false (can override on a per-test basis)
25
- Dependo::Registry[:copy_nonce] = false
26
-
27
- # default value for :cache_headers is false (can override on a per-test basis)
28
- Dependo::Registry[:cache_headers] = false
29
-
30
- # default value for :max_cache_age is nil (can override on a per-test basis)
31
- Dependo::Registry[:max_cache_age] = nil
32
-
33
- # read the config.yaml
34
- @config_pool = R509::Config::CaConfigPool.from_yaml("certificate_authorities", File.read(File.dirname(__FILE__)+"/fixtures/test_config.yaml"))
35
- end
36
-
37
- def app
38
- # this is executed after the code in each test, so if we change something in the dependo registry, it'll show up here (we will set :copy_nonce in some tests)
39
- Dependo::Registry[:ocsp_signer] = R509::Ocsp::Signer.new(
40
- :configs => @config_pool,
41
- :validity_checker => R509::Validity::Redis::Checker.new(Dependo::Registry[:redis]),
42
- :copy_nonce => Dependo::Registry[:copy_nonce]
43
- )
44
- @app ||= R509::Ocsp::Responder::Server
45
- end
46
-
47
- it "should return unauthorized on a GET which does not match any configured CA" do
48
- get '/MFEwTzBNMEswSTAJBgUrDgMCGgUABBQ1mI4Ww4R5LZiQ295pj4OF%2F44yyAQUyk7dWyc1Kdn27sPlU%2B%2BkwBmWHa8CEFqb7H4xpqYH6ed2G0%2BPMG4%3D'
49
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
50
- ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_UNAUTHORIZED
51
- last_response.content_type.should == "application/ocsp-response"
52
- last_response.should be_ok
53
- end
54
-
55
- it "should return a valid (UNKNOWN) response on a GET request from the test_ca CA" do
56
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({})
57
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "UNKNOWN")
58
-
59
- get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D'
60
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
61
- ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
62
- ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
63
- ocsp_response.basic.status[0][0].serial.should == 1051177536915098490149656742929223623669143613238
64
- ocsp_response.verify(@test_ca_cert).should == true
65
- last_response.content_type.should == "application/ocsp-response"
66
- last_response.should be_ok
67
- end
68
-
69
- it "should return a valid (REVOKED) response on a GET request from the test_ca CA" do
70
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({"status" => R509::Validity::REVOKED})
71
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "REVOKED")
72
-
73
- get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D'
74
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
75
- ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
76
- ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_REVOKED
77
- ocsp_response.basic.status[0][0].serial.should == 1051177536915098490149656742929223623669143613238
78
- ocsp_response.verify(@test_ca_cert).should == true
79
- last_response.content_type.should == "application/ocsp-response"
80
- last_response.should be_ok
81
- end
82
-
83
- it "should return a valid (VALID) response on a GET request from the test_ca CA" do
84
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({"status" => R509::Validity::VALID})
85
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "VALID")
86
-
87
- get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D'
88
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
89
- ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
90
- ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_GOOD
91
- ocsp_response.basic.status[0][0].serial.should == 1051177536915098490149656742929223623669143613238
92
- ocsp_response.verify(@test_ca_cert).should == true
93
- last_response.content_type.should == "application/ocsp-response"
94
- last_response.should be_ok
95
- end
96
-
97
- it "should return a valid (VALID) response on a GET request with extra leading slashes from the test_ca CA" do
98
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({"status" => R509::Validity::VALID})
99
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "VALID")
100
-
101
- get '/%2F%2FMFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D'
102
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
103
- ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
104
- ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_GOOD
105
- ocsp_response.basic.status[0][0].serial.should == 1051177536915098490149656742929223623669143613238
106
- ocsp_response.verify(@test_ca_cert).should == true
107
- last_response.content_type.should == "application/ocsp-response"
108
- last_response.should be_ok
109
- end
110
-
111
- it "should return a valid (VALID) response on a GET request from a second configured CA (second_ca)" do
112
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA:773553085290984246110251380739025914079776985795").and_return({"status" => R509::Validity::VALID})
113
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA", "773553085290984246110251380739025914079776985795", "VALID")
114
-
115
- get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBT1kOLWHXbHiKP3sVPVxVziq%2FMqIwQUP8ezIf8yhMLgHnccSKJLQdhDaVkCFQCHf1HsjUAACwcp3qQL4IxclfXSww%3D%3D'
116
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
117
- ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
118
- ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_GOOD
119
- ocsp_response.basic.status[0][0].serial.should == 773553085290984246110251380739025914079776985795
120
- ocsp_response.verify(@test_ca_cert).should == false
121
- ocsp_response.verify(@second_ca_cert).should == true
122
- last_response.content_type.should == "application/ocsp-response"
123
- last_response.should be_ok
124
- end
125
-
126
- it "should return unauthorized on a POST which does not match any configured CA" do
127
- der = Base64.decode64(URI.decode("MFEwTzBNMEswSTAJBgUrDgMCGgUABBQ1mI4Ww4R5LZiQ295pj4OF%2F44yyAQUyk7dWyc1Kdn27sPlU%2B%2BkwBmWHa8CEFqb7H4xpqYH6ed2G0%2BPMG4%3D"))
128
- post '/', der, "CONTENT_TYPE" => "application/ocsp-request"
129
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
130
- ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_UNAUTHORIZED
131
- last_response.content_type.should == "application/ocsp-response"
132
- last_response.should be_ok
133
- end
134
-
135
- it "should return a valid (UNKNOWN) response on a POST request from the test_ca CA" do
136
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({})
137
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "UNKNOWN")
138
-
139
- der = Base64.decode64(URI.decode("MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D"))
140
- post '/', der, "CONTENT_TYPE" => "application/ocsp-request"
141
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
142
- ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
143
- ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
144
- ocsp_response.basic.status[0][0].serial.should == 1051177536915098490149656742929223623669143613238
145
- ocsp_response.verify(@test_ca_cert).should == true
146
- last_response.content_type.should == "application/ocsp-response"
147
- last_response.should be_ok
148
- end
149
-
150
- it "should return a valid (REVOKED) response on a POST request from the test_ca CA" do
151
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({"status" => R509::Validity::REVOKED})
152
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "REVOKED")
153
-
154
- der = Base64.decode64(URI.decode("MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D"))
155
- post '/', der, "CONTENT_TYPE" => "application/ocsp-request"
156
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
157
- ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
158
- ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_REVOKED
159
- ocsp_response.basic.status[0][0].serial.should == 1051177536915098490149656742929223623669143613238
160
- ocsp_response.verify(@test_ca_cert).should == true
161
- last_response.content_type.should == "application/ocsp-response"
162
- last_response.should be_ok
163
- end
164
-
165
- it "should return a valid (VALID) response on a POST request from the test_ca CA" do
166
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({"status" => R509::Validity::VALID})
167
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "VALID")
168
-
169
- der = Base64.decode64(URI.decode("MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D"))
170
- post '/', der, "CONTENT_TYPE" => "application/ocsp-request"
171
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
172
- ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
173
- ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_GOOD
174
- ocsp_response.basic.status[0][0].serial.should == 1051177536915098490149656742929223623669143613238
175
- ocsp_response.verify(@test_ca_cert).should == true
176
- last_response.content_type.should == "application/ocsp-response"
177
- last_response.should be_ok
178
- end
179
-
180
- it "should return a valid (VALID) response on a POST request from a second configured CA (second_ca)" do
181
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA:773553085290984246110251380739025914079776985795").and_return({"status" => R509::Validity::VALID})
182
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA", "773553085290984246110251380739025914079776985795", "VALID")
183
-
184
- der = Base64.decode64(URI.decode("MFYwVDBSMFAwTjAJBgUrDgMCGgUABBT1kOLWHXbHiKP3sVPVxVziq%2FMqIwQUP8ezIf8yhMLgHnccSKJLQdhDaVkCFQCHf1HsjUAACwcp3qQL4IxclfXSww%3D%3D"))
185
- post '/', der, "CONTENT_TYPE" => "application/ocsp-request"
186
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
187
- ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
188
- ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_GOOD
189
- ocsp_response.basic.status[0][0].serial.should == 773553085290984246110251380739025914079776985795
190
- ocsp_response.verify(@test_ca_cert).should == false
191
- ocsp_response.verify(@second_ca_cert).should == true
192
- last_response.content_type.should == "application/ocsp-response"
193
- last_response.should be_ok
194
- end
195
-
196
- it "should return 200 OK when querying status and redis is available" do
197
- @redis.should_receive(:ping).and_return("PONG")
198
- get '/status'
199
- last_response.should be_ok
200
- end
201
-
202
- it "should return 500 DOWN when querying status with redis unavailable" do
203
- @redis.should_receive(:ping).and_raise(StandardError)
204
- get '/status'
205
- last_response.should_not be_ok
206
- last_response.body.should == "Down"
207
- end
208
-
209
- it "a malformed request should return a proper OCSP response (GET)" do
210
- get '/Msdfsfsdf'
211
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
212
- ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_MALFORMEDREQUEST
213
- last_response.content_type.should == "application/ocsp-response"
214
- last_response.should be_ok
215
- end
216
-
217
- it "a malformed request should return a proper OCSP response (POST)" do
218
- post '/', 'Mdskfsdf', "CONTENT_TYPE" => "application/ocsp-request"
219
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
220
- ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_MALFORMEDREQUEST
221
- last_response.content_type.should == "application/ocsp-response"
222
- last_response.should be_ok
223
- end
224
-
225
- it "copies nonce when copy_nonce is true" do
226
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:872625873161273451176241581705670534707360122361").and_return({"status" => R509::Validity::VALID})
227
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "872625873161273451176241581705670534707360122361", "VALID")
228
-
229
- # set to true for this test (this works because the app doesn't get set up until after this code)
230
- Dependo::Registry[:copy_nonce] = true
231
-
232
- get '/MHsweTBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQCY2eXAtMNzVS33fF0PHrUSjklF%2BaIjMCEwHwYJKwYBBQUHMAECBBIEEDTJniOQonxCRmmHAHCVstw%3D'
233
- request = OpenSSL::OCSP::Request.new(Base64.decode64("MHsweTBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQCY2eXAtMNzVS33fF0PHrUSjklF+aIjMCEwHwYJKwYBBQUHMAECBBIEEDTJniOQonxCRmmHAHCVstw="))
234
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
235
- request.check_nonce(ocsp_response.basic).should == R509::Ocsp::Request::Nonce::PRESENT_AND_EQUAL
236
-
237
- end
238
-
239
- it "doesn't copy nonce when copy_nonce is false" do
240
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:872625873161273451176241581705670534707360122361").and_return({"status" => R509::Validity::VALID})
241
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "872625873161273451176241581705670534707360122361", "VALID")
242
-
243
- # set to false for this test (this works because the app doesn't get set up until after this code)
244
- Dependo::Registry[:copy_nonce] = false
245
-
246
- get '/MHsweTBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQCY2eXAtMNzVS33fF0PHrUSjklF%2BaIjMCEwHwYJKwYBBQUHMAECBBIEEDTJniOQonxCRmmHAHCVstw%3D'
247
- request = OpenSSL::OCSP::Request.new(Base64.decode64("MHsweTBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQCY2eXAtMNzVS33fF0PHrUSjklF+aIjMCEwHwYJKwYBBQUHMAECBBIEEDTJniOQonxCRmmHAHCVstw="))
248
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
249
- request.check_nonce(ocsp_response.basic).should == R509::Ocsp::Request::Nonce::REQUEST_ONLY
250
- end
251
-
252
- it "returns caching headers for GET when cache_headers is true and no nonce is present" do
253
- Dependo::Registry[:cache_headers] = true
254
-
255
- now = Time.now
256
- Time.stub!(:now).and_return(now)
257
-
258
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA:773553085290984246110251380739025914079776985795").and_return({"status" => R509::Validity::VALID})
259
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA", "773553085290984246110251380739025914079776985795", "VALID")
260
-
261
- get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBT1kOLWHXbHiKP3sVPVxVziq%2FMqIwQUP8ezIf8yhMLgHnccSKJLQdhDaVkCFQCHf1HsjUAACwcp3qQL4IxclfXSww%3D%3D'
262
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
263
- last_response.headers.size.should == 6
264
- last_response.headers["Last-Modified"].should == Time.now.httpdate
265
- last_response.headers["ETag"].should == OpenSSL::Digest::SHA1.new(ocsp_response.to_der).to_s
266
- last_response.headers["Expires"].should == ocsp_response.basic.status[0][5].httpdate
267
- max_age = ocsp_response.basic.status[0][5] - now
268
- last_response.headers["Cache-Control"].should == "max-age=#{max_age.to_i}, public, no-transform, must-revalidate"
269
- end
270
-
271
- it "returns no caching headers for GET when cache_headers is false and no nonce is present" do
272
- Dependo::Registry[:cache_headers] = false
273
-
274
- now = Time.now
275
- Time.stub!(:now).and_return(now)
276
-
277
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA:773553085290984246110251380739025914079776985795").and_return({"status" => R509::Validity::VALID})
278
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA", "773553085290984246110251380739025914079776985795", "VALID")
279
-
280
- get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBT1kOLWHXbHiKP3sVPVxVziq%2FMqIwQUP8ezIf8yhMLgHnccSKJLQdhDaVkCFQCHf1HsjUAACwcp3qQL4IxclfXSww%3D%3D'
281
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
282
- last_response.headers.size.should == 2
283
- end
284
-
285
- it "returns no caching headers for GET when cache_headers is true and a nonce is present" do
286
- Dependo::Registry[:cache_headers] = true
287
-
288
- now = Time.now
289
- Time.stub!(:now).and_return(now)
290
-
291
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:872625873161273451176241581705670534707360122361").and_return({"status" => R509::Validity::VALID})
292
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "872625873161273451176241581705670534707360122361", "VALID")
293
-
294
- get '/MHsweTBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQCY2eXAtMNzVS33fF0PHrUSjklF%2BaIjMCEwHwYJKwYBBQUHMAECBBIEEDTJniOQonxCRmmHAHCVstw%3D'
295
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
296
- last_response.headers.size.should == 2
297
- end
298
-
299
- it "returns no caching headers for GET when cache_headers is false and a nonce is present" do
300
- Dependo::Registry[:cache_headers] = false
301
-
302
- now = Time.now
303
- Time.stub!(:now).and_return(now)
304
-
305
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:872625873161273451176241581705670534707360122361").and_return({"status" => R509::Validity::VALID})
306
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "872625873161273451176241581705670534707360122361", "VALID")
307
-
308
- get '/MHsweTBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQCY2eXAtMNzVS33fF0PHrUSjklF%2BaIjMCEwHwYJKwYBBQUHMAECBBIEEDTJniOQonxCRmmHAHCVstw%3D'
309
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
310
- last_response.headers.size.should == 2
311
- end
312
-
313
- it "returns custom max_cache_age when it's set properly" do
314
- Dependo::Registry[:cache_headers] = true
315
- Dependo::Registry[:max_cache_age] = 600
316
-
317
- now = Time.now
318
- Time.stub!(:now).and_return(now)
319
-
320
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA:773553085290984246110251380739025914079776985795").and_return({"status" => R509::Validity::VALID})
321
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA", "773553085290984246110251380739025914079776985795", "VALID")
322
-
323
- get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBT1kOLWHXbHiKP3sVPVxVziq%2FMqIwQUP8ezIf8yhMLgHnccSKJLQdhDaVkCFQCHf1HsjUAACwcp3qQL4IxclfXSww%3D%3D'
324
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
325
- last_response.headers.size.should == 6
326
- last_response.headers["Last-Modified"].should == now.httpdate
327
- last_response.headers["ETag"].should == OpenSSL::Digest::SHA1.new(ocsp_response.to_der).to_s
328
- last_response.headers["Expires"].should == ocsp_response.basic.status[0][5].httpdate
329
- last_response.headers["Cache-Control"].should == "max-age=600, public, no-transform, must-revalidate"
330
- end
331
-
332
- it "returns default max_cache_age if custom age is too large" do
333
- Dependo::Registry[:cache_headers] = true
334
- Dependo::Registry[:max_cache_age] = 950000
335
-
336
- now = Time.now
337
- Time.stub!(:now).and_return(now)
338
-
339
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA:773553085290984246110251380739025914079776985795").and_return({"status" => R509::Validity::VALID})
340
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA", "773553085290984246110251380739025914079776985795", "VALID")
341
-
342
- get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBT1kOLWHXbHiKP3sVPVxVziq%2FMqIwQUP8ezIf8yhMLgHnccSKJLQdhDaVkCFQCHf1HsjUAACwcp3qQL4IxclfXSww%3D%3D'
343
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
344
- last_response.headers.size.should == 6
345
- last_response.headers["Last-Modified"].should == now.httpdate
346
- last_response.headers["ETag"].should == OpenSSL::Digest::SHA1.new(ocsp_response.to_der).to_s
347
- last_response.headers["Expires"].should == ocsp_response.basic.status[0][5].httpdate
348
- max_age = ocsp_response.basic.status[0][5] - now
349
- last_response.headers["Cache-Control"].should == "max-age=#{max_age.to_i}, public, no-transform, must-revalidate"
350
- end
351
-
352
- it "returns no caching headers for GET when cache_headers is false" do
353
- Dependo::Registry[:cache_headers] = false
354
-
355
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA:773553085290984246110251380739025914079776985795").and_return({"status" => R509::Validity::VALID})
356
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA", "773553085290984246110251380739025914079776985795", "VALID")
357
-
358
- get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBT1kOLWHXbHiKP3sVPVxVziq%2FMqIwQUP8ezIf8yhMLgHnccSKJLQdhDaVkCFQCHf1HsjUAACwcp3qQL4IxclfXSww%3D%3D'
359
- last_response.content_type.should == "application/ocsp-response"
360
- last_response.headers.size.should == 2
361
- last_response.should be_ok
362
- end
363
-
364
- it "returns no caching headers for POST when cache_headers is true" do
365
- Dependo::Registry[:cache_headers] = true
366
-
367
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({"status" => R509::Validity::VALID})
368
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "VALID")
369
-
370
- der = Base64.decode64(URI.decode("MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D"))
371
- post '/', der, "CONTENT_TYPE" => "application/ocsp-request"
372
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
373
- last_response.content_type.should == "application/ocsp-response"
374
- last_response.headers.size.should == 2
375
- last_response.should be_ok
376
- end
377
-
378
- it "returns no caching headers for POST when cache_headers is false" do
379
- Dependo::Registry[:cache_headers] = false
380
-
381
- @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({"status" => R509::Validity::VALID})
382
- @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "VALID")
383
-
384
- der = Base64.decode64(URI.decode("MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D"))
385
- post '/', der, "CONTENT_TYPE" => "application/ocsp-request"
386
- ocsp_response = R509::Ocsp::Response.parse(last_response.body)
387
- last_response.content_type.should == "application/ocsp-response"
388
- last_response.headers.size.should == 2
389
- last_response.should be_ok
390
- end
391
-
392
- it "should reload and print config when receiving a SIGUSR2" do
393
- config = double("config")
394
- stub_const("R509::Ocsp::Responder::OcspConfig",config)
395
- #R509::Ocsp::Responder::OcspConfig = double("config")
396
- R509::Ocsp::Responder::OcspConfig.should_receive(:load_config)
397
- R509::Ocsp::Responder::OcspConfig.should_receive(:print_config)
398
- Process.kill :USR2, Process.pid
399
- end
3
+ require 'r509/validity/redis'
4
+
5
+
6
+ describe R509::OCSP::Responder::Server do
7
+ before :all do
8
+ @test_ca_cert = OpenSSL::X509::Certificate.new(File.read(Pathname.new(__FILE__).dirname + "fixtures/test_ca.cer"))
9
+ @second_ca_cert = OpenSSL::X509::Certificate.new(File.read(Pathname.new(__FILE__).dirname + "fixtures/second_ca.cer"))
10
+ end
11
+
12
+ before :each do
13
+ # clear the dependo before each test
14
+ Dependo::Registry.clear
15
+ Dependo::Registry[:log] = Logger.new(nil)
16
+
17
+ # we always want to mock with a new redis
18
+ @redis = double("redis")
19
+ Dependo::Registry[:validity_checker] = R509::Validity::Redis::Checker.new @redis
20
+
21
+ # and we want to mock the stats recorder
22
+ @stats = double("stats")
23
+ Dependo::Registry[:stats] = @stats
24
+
25
+ # default value for :copy_nonce is false (can override on a per-test basis)
26
+ Dependo::Registry[:copy_nonce] = false
27
+
28
+ # default value for :cache_headers is false (can override on a per-test basis)
29
+ Dependo::Registry[:cache_headers] = false
30
+
31
+ # default value for :max_cache_age is nil (can override on a per-test basis)
32
+ Dependo::Registry[:max_cache_age] = nil
33
+
34
+ # read the config.yaml
35
+ @config_pool = R509::Config::CAConfigPool.from_yaml("certificate_authorities", File.read(File.dirname(__FILE__)+"/fixtures/test_config.yaml"))
36
+ end
37
+
38
+ def app
39
+ # this is executed after the code in each test, so if we change something in the dependo registry, it'll show up here (we will set :copy_nonce in some tests)
40
+ Dependo::Registry[:ocsp_signer] = R509::OCSP::Signer.new(
41
+ :configs => @config_pool,
42
+ :validity_checker => Dependo::Registry[:validity_checker],
43
+ :copy_nonce => Dependo::Registry[:copy_nonce]
44
+ )
45
+ @app ||= R509::OCSP::Responder::Server
46
+ end
47
+
48
+ it "should return unauthorized on a GET which does not match any configured CA" do
49
+ get '/MFEwTzBNMEswSTAJBgUrDgMCGgUABBQ1mI4Ww4R5LZiQ295pj4OF%2F44yyAQUyk7dWyc1Kdn27sPlU%2B%2BkwBmWHa8CEFqb7H4xpqYH6ed2G0%2BPMG4%3D'
50
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
51
+ ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_UNAUTHORIZED
52
+ last_response.content_type.should == "application/ocsp-response"
53
+ last_response.should be_ok
54
+ end
55
+
56
+ it "should return a valid (UNKNOWN) response on a GET request from the test_ca CA" do
57
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({})
58
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "UNKNOWN")
59
+
60
+ get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D'
61
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
62
+ ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
63
+ ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
64
+ ocsp_response.basic.status[0][0].serial.should == 1051177536915098490149656742929223623669143613238
65
+ ocsp_response.verify(@test_ca_cert).should == true
66
+ last_response.content_type.should == "application/ocsp-response"
67
+ last_response.should be_ok
68
+ end
69
+
70
+ it "should return a valid (REVOKED) response on a GET request from the test_ca CA" do
71
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({"status" => R509::Validity::REVOKED})
72
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "REVOKED")
73
+
74
+ get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D'
75
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
76
+ ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
77
+ ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_REVOKED
78
+ ocsp_response.basic.status[0][0].serial.should == 1051177536915098490149656742929223623669143613238
79
+ ocsp_response.verify(@test_ca_cert).should == true
80
+ last_response.content_type.should == "application/ocsp-response"
81
+ last_response.should be_ok
82
+ end
83
+
84
+ it "should return a valid (VALID) response on a GET request from the test_ca CA" do
85
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({"status" => R509::Validity::VALID})
86
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "VALID")
87
+
88
+ get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D'
89
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
90
+ ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
91
+ ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_GOOD
92
+ ocsp_response.basic.status[0][0].serial.should == 1051177536915098490149656742929223623669143613238
93
+ ocsp_response.verify(@test_ca_cert).should == true
94
+ last_response.content_type.should == "application/ocsp-response"
95
+ last_response.should be_ok
96
+ end
97
+
98
+ it "should return a valid (VALID) response on a GET request with extra leading slashes from the test_ca CA" do
99
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({"status" => R509::Validity::VALID})
100
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "VALID")
101
+
102
+ get '/%2F%2FMFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D'
103
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
104
+ ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
105
+ ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_GOOD
106
+ ocsp_response.basic.status[0][0].serial.should == 1051177536915098490149656742929223623669143613238
107
+ ocsp_response.verify(@test_ca_cert).should == true
108
+ last_response.content_type.should == "application/ocsp-response"
109
+ last_response.should be_ok
110
+ end
111
+
112
+ it "should return a valid (VALID) response on a GET request from a second configured CA (second_ca)" do
113
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA:773553085290984246110251380739025914079776985795").and_return({"status" => R509::Validity::VALID})
114
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA", "773553085290984246110251380739025914079776985795", "VALID")
115
+
116
+ get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBT1kOLWHXbHiKP3sVPVxVziq%2FMqIwQUP8ezIf8yhMLgHnccSKJLQdhDaVkCFQCHf1HsjUAACwcp3qQL4IxclfXSww%3D%3D'
117
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
118
+ ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
119
+ ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_GOOD
120
+ ocsp_response.basic.status[0][0].serial.should == 773553085290984246110251380739025914079776985795
121
+ ocsp_response.verify(@test_ca_cert).should == false
122
+ ocsp_response.verify(@second_ca_cert).should == true
123
+ last_response.content_type.should == "application/ocsp-response"
124
+ last_response.should be_ok
125
+ end
126
+
127
+ it "should return unauthorized on a POST which does not match any configured CA" do
128
+ der = Base64.decode64(URI.decode("MFEwTzBNMEswSTAJBgUrDgMCGgUABBQ1mI4Ww4R5LZiQ295pj4OF%2F44yyAQUyk7dWyc1Kdn27sPlU%2B%2BkwBmWHa8CEFqb7H4xpqYH6ed2G0%2BPMG4%3D"))
129
+ post '/', der, "CONTENT_TYPE" => "application/ocsp-request"
130
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
131
+ ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_UNAUTHORIZED
132
+ last_response.content_type.should == "application/ocsp-response"
133
+ last_response.should be_ok
134
+ end
135
+
136
+ it "should return a valid (UNKNOWN) response on a POST request from the test_ca CA" do
137
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({})
138
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "UNKNOWN")
139
+
140
+ der = Base64.decode64(URI.decode("MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D"))
141
+ post '/', der, "CONTENT_TYPE" => "application/ocsp-request"
142
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
143
+ ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
144
+ ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN
145
+ ocsp_response.basic.status[0][0].serial.should == 1051177536915098490149656742929223623669143613238
146
+ ocsp_response.verify(@test_ca_cert).should == true
147
+ last_response.content_type.should == "application/ocsp-response"
148
+ last_response.should be_ok
149
+ end
150
+
151
+ it "should return a valid (REVOKED) response on a POST request from the test_ca CA" do
152
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({"status" => R509::Validity::REVOKED})
153
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "REVOKED")
154
+
155
+ der = Base64.decode64(URI.decode("MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D"))
156
+ post '/', der, "CONTENT_TYPE" => "application/ocsp-request"
157
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
158
+ ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
159
+ ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_REVOKED
160
+ ocsp_response.basic.status[0][0].serial.should == 1051177536915098490149656742929223623669143613238
161
+ ocsp_response.verify(@test_ca_cert).should == true
162
+ last_response.content_type.should == "application/ocsp-response"
163
+ last_response.should be_ok
164
+ end
165
+
166
+ it "should return a valid (VALID) response on a POST request from the test_ca CA" do
167
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({"status" => R509::Validity::VALID})
168
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "VALID")
169
+
170
+ der = Base64.decode64(URI.decode("MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D"))
171
+ post '/', der, "CONTENT_TYPE" => "application/ocsp-request"
172
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
173
+ ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
174
+ ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_GOOD
175
+ ocsp_response.basic.status[0][0].serial.should == 1051177536915098490149656742929223623669143613238
176
+ ocsp_response.verify(@test_ca_cert).should == true
177
+ last_response.content_type.should == "application/ocsp-response"
178
+ last_response.should be_ok
179
+ end
180
+
181
+ it "should return a valid (VALID) response on a POST request from a second configured CA (second_ca)" do
182
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA:773553085290984246110251380739025914079776985795").and_return({"status" => R509::Validity::VALID})
183
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA", "773553085290984246110251380739025914079776985795", "VALID")
184
+
185
+ der = Base64.decode64(URI.decode("MFYwVDBSMFAwTjAJBgUrDgMCGgUABBT1kOLWHXbHiKP3sVPVxVziq%2FMqIwQUP8ezIf8yhMLgHnccSKJLQdhDaVkCFQCHf1HsjUAACwcp3qQL4IxclfXSww%3D%3D"))
186
+ post '/', der, "CONTENT_TYPE" => "application/ocsp-request"
187
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
188
+ ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
189
+ ocsp_response.basic.status[0][1].should == OpenSSL::OCSP::V_CERTSTATUS_GOOD
190
+ ocsp_response.basic.status[0][0].serial.should == 773553085290984246110251380739025914079776985795
191
+ ocsp_response.verify(@test_ca_cert).should == false
192
+ ocsp_response.verify(@second_ca_cert).should == true
193
+ last_response.content_type.should == "application/ocsp-response"
194
+ last_response.should be_ok
195
+ end
196
+
197
+ it "should return 200 OK when querying status and redis is available" do
198
+ @redis.should_receive(:ping).and_return("PONG")
199
+ get '/status'
200
+ last_response.should be_ok
201
+ end
202
+
203
+ it "should return 500 DOWN when querying status with redis unavailable" do
204
+ @redis.should_receive(:ping).and_raise(StandardError)
205
+ get '/status'
206
+ last_response.should_not be_ok
207
+ last_response.body.should == "Down"
208
+ end
209
+
210
+ it "should return 500 DOWN when querying status with redis responding incorrectly" do
211
+ @redis.should_receive(:ping).and_return("")
212
+ get '/status'
213
+ last_response.should_not be_ok
214
+ last_response.body.should == "Down"
215
+ end
216
+
217
+ it "a malformed request should return a proper OCSP response (GET)" do
218
+ get '/Msdfsfsdf'
219
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
220
+ ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_MALFORMEDREQUEST
221
+ last_response.content_type.should == "application/ocsp-response"
222
+ last_response.should be_ok
223
+ end
224
+
225
+ it "a malformed request should return a proper OCSP response (POST)" do
226
+ post '/', 'Mdskfsdf', "CONTENT_TYPE" => "application/ocsp-request"
227
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
228
+ ocsp_response.status.should == OpenSSL::OCSP::RESPONSE_STATUS_MALFORMEDREQUEST
229
+ last_response.content_type.should == "application/ocsp-response"
230
+ last_response.should be_ok
231
+ end
232
+
233
+ it "copies nonce when copy_nonce is true" do
234
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:872625873161273451176241581705670534707360122361").and_return({"status" => R509::Validity::VALID})
235
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "872625873161273451176241581705670534707360122361", "VALID")
236
+
237
+ # set to true for this test (this works because the app doesn't get set up until after this code)
238
+ Dependo::Registry[:copy_nonce] = true
239
+
240
+ get '/MHsweTBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQCY2eXAtMNzVS33fF0PHrUSjklF%2BaIjMCEwHwYJKwYBBQUHMAECBBIEEDTJniOQonxCRmmHAHCVstw%3D'
241
+ request = OpenSSL::OCSP::Request.new(Base64.decode64("MHsweTBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQCY2eXAtMNzVS33fF0PHrUSjklF+aIjMCEwHwYJKwYBBQUHMAECBBIEEDTJniOQonxCRmmHAHCVstw="))
242
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
243
+ request.check_nonce(ocsp_response.basic).should == R509::OCSP::Request::Nonce::PRESENT_AND_EQUAL
244
+
245
+ end
246
+
247
+ it "doesn't copy nonce when copy_nonce is false" do
248
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:872625873161273451176241581705670534707360122361").and_return({"status" => R509::Validity::VALID})
249
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "872625873161273451176241581705670534707360122361", "VALID")
250
+
251
+ # set to false for this test (this works because the app doesn't get set up until after this code)
252
+ Dependo::Registry[:copy_nonce] = false
253
+
254
+ get '/MHsweTBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQCY2eXAtMNzVS33fF0PHrUSjklF%2BaIjMCEwHwYJKwYBBQUHMAECBBIEEDTJniOQonxCRmmHAHCVstw%3D'
255
+ request = OpenSSL::OCSP::Request.new(Base64.decode64("MHsweTBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQCY2eXAtMNzVS33fF0PHrUSjklF+aIjMCEwHwYJKwYBBQUHMAECBBIEEDTJniOQonxCRmmHAHCVstw="))
256
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
257
+ request.check_nonce(ocsp_response.basic).should == R509::OCSP::Request::Nonce::REQUEST_ONLY
258
+ end
259
+
260
+ it "returns caching headers for GET when cache_headers is true and no nonce is present" do
261
+ Dependo::Registry[:cache_headers] = true
262
+
263
+ now = Time.now
264
+ Time.stub!(:now).and_return(now)
265
+
266
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA:773553085290984246110251380739025914079776985795").and_return({"status" => R509::Validity::VALID})
267
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA", "773553085290984246110251380739025914079776985795", "VALID")
268
+
269
+ get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBT1kOLWHXbHiKP3sVPVxVziq%2FMqIwQUP8ezIf8yhMLgHnccSKJLQdhDaVkCFQCHf1HsjUAACwcp3qQL4IxclfXSww%3D%3D'
270
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
271
+ last_response.headers.size.should == 6
272
+ last_response.headers["Last-Modified"].should == Time.now.httpdate
273
+ last_response.headers["ETag"].should == OpenSSL::Digest::SHA1.new(ocsp_response.to_der).to_s
274
+ last_response.headers["Expires"].should == ocsp_response.basic.status[0][5].httpdate
275
+ max_age = ocsp_response.basic.status[0][5] - now
276
+ last_response.headers["Cache-Control"].should == "max-age=#{max_age.to_i}, public, no-transform, must-revalidate"
277
+ end
278
+
279
+ it "returns no caching headers for GET when cache_headers is false and no nonce is present" do
280
+ Dependo::Registry[:cache_headers] = false
281
+
282
+ now = Time.now
283
+ Time.stub!(:now).and_return(now)
284
+
285
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA:773553085290984246110251380739025914079776985795").and_return({"status" => R509::Validity::VALID})
286
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA", "773553085290984246110251380739025914079776985795", "VALID")
287
+
288
+ get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBT1kOLWHXbHiKP3sVPVxVziq%2FMqIwQUP8ezIf8yhMLgHnccSKJLQdhDaVkCFQCHf1HsjUAACwcp3qQL4IxclfXSww%3D%3D'
289
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
290
+ last_response.headers.size.should == 2
291
+ end
292
+
293
+ it "returns no caching headers for GET when cache_headers is true and a nonce is present" do
294
+ Dependo::Registry[:cache_headers] = true
295
+
296
+ now = Time.now
297
+ Time.stub!(:now).and_return(now)
298
+
299
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:872625873161273451176241581705670534707360122361").and_return({"status" => R509::Validity::VALID})
300
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "872625873161273451176241581705670534707360122361", "VALID")
301
+
302
+ get '/MHsweTBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQCY2eXAtMNzVS33fF0PHrUSjklF%2BaIjMCEwHwYJKwYBBQUHMAECBBIEEDTJniOQonxCRmmHAHCVstw%3D'
303
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
304
+ last_response.headers.size.should == 2
305
+ end
306
+
307
+ it "returns no caching headers for GET when cache_headers is false and a nonce is present" do
308
+ Dependo::Registry[:cache_headers] = false
309
+
310
+ now = Time.now
311
+ Time.stub!(:now).and_return(now)
312
+
313
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:872625873161273451176241581705670534707360122361").and_return({"status" => R509::Validity::VALID})
314
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "872625873161273451176241581705670534707360122361", "VALID")
315
+
316
+ get '/MHsweTBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQCY2eXAtMNzVS33fF0PHrUSjklF%2BaIjMCEwHwYJKwYBBQUHMAECBBIEEDTJniOQonxCRmmHAHCVstw%3D'
317
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
318
+ last_response.headers.size.should == 2
319
+ end
320
+
321
+ it "returns custom max_cache_age when it's set properly" do
322
+ Dependo::Registry[:cache_headers] = true
323
+ Dependo::Registry[:max_cache_age] = 600
324
+
325
+ now = Time.now
326
+ Time.stub!(:now).and_return(now)
327
+
328
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA:773553085290984246110251380739025914079776985795").and_return({"status" => R509::Validity::VALID})
329
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA", "773553085290984246110251380739025914079776985795", "VALID")
330
+
331
+ get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBT1kOLWHXbHiKP3sVPVxVziq%2FMqIwQUP8ezIf8yhMLgHnccSKJLQdhDaVkCFQCHf1HsjUAACwcp3qQL4IxclfXSww%3D%3D'
332
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
333
+ last_response.headers.size.should == 6
334
+ last_response.headers["Last-Modified"].should == now.httpdate
335
+ last_response.headers["ETag"].should == OpenSSL::Digest::SHA1.new(ocsp_response.to_der).to_s
336
+ last_response.headers["Expires"].should == ocsp_response.basic.status[0][5].httpdate
337
+ last_response.headers["Cache-Control"].should == "max-age=600, public, no-transform, must-revalidate"
338
+ end
339
+
340
+ it "returns default max_cache_age if custom age is too large" do
341
+ Dependo::Registry[:cache_headers] = true
342
+ Dependo::Registry[:max_cache_age] = 950000
343
+
344
+ now = Time.now
345
+ Time.stub!(:now).and_return(now)
346
+
347
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA:773553085290984246110251380739025914079776985795").and_return({"status" => R509::Validity::VALID})
348
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA", "773553085290984246110251380739025914079776985795", "VALID")
349
+
350
+ get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBT1kOLWHXbHiKP3sVPVxVziq%2FMqIwQUP8ezIf8yhMLgHnccSKJLQdhDaVkCFQCHf1HsjUAACwcp3qQL4IxclfXSww%3D%3D'
351
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
352
+ last_response.headers.size.should == 6
353
+ last_response.headers["Last-Modified"].should == now.httpdate
354
+ last_response.headers["ETag"].should == OpenSSL::Digest::SHA1.new(ocsp_response.to_der).to_s
355
+ last_response.headers["Expires"].should == ocsp_response.basic.status[0][5].httpdate
356
+ max_age = ocsp_response.basic.status[0][5] - now
357
+ last_response.headers["Cache-Control"].should == "max-age=#{max_age.to_i}, public, no-transform, must-revalidate"
358
+ end
359
+
360
+ it "returns no caching headers for GET when cache_headers is false" do
361
+ Dependo::Registry[:cache_headers] = false
362
+
363
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA:773553085290984246110251380739025914079776985795").and_return({"status" => R509::Validity::VALID})
364
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=R509, Ltd/CN=R509 Secondary Test CA", "773553085290984246110251380739025914079776985795", "VALID")
365
+
366
+ get '/MFYwVDBSMFAwTjAJBgUrDgMCGgUABBT1kOLWHXbHiKP3sVPVxVziq%2FMqIwQUP8ezIf8yhMLgHnccSKJLQdhDaVkCFQCHf1HsjUAACwcp3qQL4IxclfXSww%3D%3D'
367
+ last_response.content_type.should == "application/ocsp-response"
368
+ last_response.headers.size.should == 2
369
+ last_response.should be_ok
370
+ end
371
+
372
+ it "returns no caching headers for POST when cache_headers is true" do
373
+ Dependo::Registry[:cache_headers] = true
374
+
375
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({"status" => R509::Validity::VALID})
376
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "VALID")
377
+
378
+ der = Base64.decode64(URI.decode("MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D"))
379
+ post '/', der, "CONTENT_TYPE" => "application/ocsp-request"
380
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
381
+ last_response.content_type.should == "application/ocsp-response"
382
+ last_response.headers.size.should == 2
383
+ last_response.should be_ok
384
+ end
385
+
386
+ it "returns no caching headers for POST when cache_headers is false" do
387
+ Dependo::Registry[:cache_headers] = false
388
+
389
+ @redis.should_receive(:hgetall).with("cert:/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA:1051177536915098490149656742929223623669143613238").and_return({"status" => R509::Validity::VALID})
390
+ @stats.should_receive(:record).with("/C=US/ST=Illinois/L=Chicago/O=Ruby CA Project/CN=Test CA", "1051177536915098490149656742929223623669143613238", "VALID")
391
+
392
+ der = Base64.decode64(URI.decode("MFYwVDBSMFAwTjAJBgUrDgMCGgUABBQ4ykaMB0SN9IGWx21tTHBRnmCnvQQUeXW7hDrLLN56Cb4xG0O8HCpNU1gCFQC4IG5U4zC4RYb4VQ%2B2f0zCoFCvNg%3D%3D"))
393
+ post '/', der, "CONTENT_TYPE" => "application/ocsp-request"
394
+ ocsp_response = R509::OCSP::Response.parse(last_response.body)
395
+ last_response.content_type.should == "application/ocsp-response"
396
+ last_response.headers.size.should == 2
397
+ last_response.should be_ok
398
+ end
399
+
400
+ it "should reload and print config when receiving a SIGUSR2" do
401
+ config = double("config")
402
+ stub_const("R509::OCSP::Responder::OCSPConfig",config)
403
+ #R509::OCSP::Responder::OCSPConfig = double("config")
404
+ R509::OCSP::Responder::OCSPConfig.should_receive(:load_config)
405
+ R509::OCSP::Responder::OCSPConfig.should_receive(:print_config)
406
+ Process.kill :USR2, Process.pid
407
+ end
400
408
  end