r509-ocsp-responder 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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