r509-ocsp-responder 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. data/README.md +77 -0
  2. data/Rakefile +38 -0
  3. data/doc/R509.html +115 -0
  4. data/doc/R509/Ocsp.html +130 -0
  5. data/doc/R509/Ocsp/Helper.html +126 -0
  6. data/doc/R509/Ocsp/Helper/RequestChecker.html +739 -0
  7. data/doc/R509/Ocsp/Helper/ResponseSigner.html +583 -0
  8. data/doc/R509/Ocsp/Responder.html +129 -0
  9. data/doc/R509/Ocsp/Responder/OcspConfig.html +289 -0
  10. data/doc/R509/Ocsp/Responder/Server.html +128 -0
  11. data/doc/R509/Ocsp/Responder/StatusError.html +134 -0
  12. data/doc/R509/Ocsp/Signer.html +584 -0
  13. data/doc/_index.html +197 -0
  14. data/doc/class_list.html +53 -0
  15. data/doc/css/common.css +1 -0
  16. data/doc/css/full_list.css +57 -0
  17. data/doc/css/style.css +328 -0
  18. data/doc/file.README.html +156 -0
  19. data/doc/file_list.html +55 -0
  20. data/doc/frames.html +28 -0
  21. data/doc/index.html +156 -0
  22. data/doc/js/app.js +214 -0
  23. data/doc/js/full_list.js +173 -0
  24. data/doc/js/jquery.js +4 -0
  25. data/doc/method_list.html +164 -0
  26. data/doc/top-level-namespace.html +112 -0
  27. data/lib/r509/ocsp/responder/ocsp-config.rb +35 -0
  28. data/lib/r509/ocsp/responder/server.rb +169 -0
  29. data/lib/r509/ocsp/responder/version.rb +7 -0
  30. data/lib/r509/ocsp/signer.rb +244 -0
  31. data/spec/fixtures.rb +196 -0
  32. data/spec/fixtures/cert1.pem +24 -0
  33. data/spec/fixtures/config_test_various.yaml +46 -0
  34. data/spec/fixtures/ocsptest.r509.local.pem +27 -0
  35. data/spec/fixtures/second_ca.cer +26 -0
  36. data/spec/fixtures/second_ca.key +27 -0
  37. data/spec/fixtures/stca.pem +22 -0
  38. data/spec/fixtures/stca_ocsp_request.der +0 -0
  39. data/spec/fixtures/stca_ocsp_response.der +0 -0
  40. data/spec/fixtures/test_ca.cer +22 -0
  41. data/spec/fixtures/test_ca.key +28 -0
  42. data/spec/fixtures/test_ca_ocsp.cer +26 -0
  43. data/spec/fixtures/test_ca_ocsp.key +27 -0
  44. data/spec/fixtures/test_ca_ocsp_chain.txt +48 -0
  45. data/spec/fixtures/test_ca_request.der +0 -0
  46. data/spec/fixtures/test_ca_response.der +0 -0
  47. data/spec/fixtures/test_ca_subroot.cer +25 -0
  48. data/spec/fixtures/test_ca_subroot.key +27 -0
  49. data/spec/fixtures/test_ca_subroot_ocsp.cer +25 -0
  50. data/spec/fixtures/test_ca_subroot_ocsp.key +27 -0
  51. data/spec/fixtures/test_config.yaml +17 -0
  52. data/spec/server_spec.rb +400 -0
  53. data/spec/signer_spec.rb +275 -0
  54. data/spec/spec_helper.rb +18 -0
  55. metadata +259 -0
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEogIBAAKCAQEAvVuPqX19dbEXF1ciXNF7BQpwwiNK96GkvmMIn/sCp6N+xXor
3
+ VqWX0KA6hcXWPt8BPwiRy7BwhBqrfMBXW9fFi0dGJaVB9h5dJarPBDxbMEDMhrod
4
+ ExnG2NsXN+sA9YQpE3I6UX9H3z5VMPYwJFtt5U8tGQ63Me6IbTFqn69VsYbts76S
5
+ 3xxG2FV1ibWCQg/g7HtxKL4kBH0mxkvWST5CEiBT0EoTgFLSKiuML8Vcd3qXe5vU
6
+ MKgo+vmXDXoymYvCGOefSbIDLoWvh5MCvr28OgD8q2izMVY7YRpCxbSslxGPAoB+
7
+ WIFC7VtXN+EESmjZ8XCMf3J3Gns1Ych/7/LXIQIDAQABAoIBAHfVsSY/P52y0/02
8
+ bI23GJaJE/EYqsHqbzr5q6SrEvQKeRj6huDP7TLfpAmyuTKSqNQ+VR5F6/7+bdaG
9
+ VwLNm7vYAGGkowjiEGrdHSP+GmuAJq+AqxPCdWAZzyjZNYMq/1/KI3QeC9sRNJLG
10
+ ypLHtdWv9Mdt06vq3DXWVzb1nFK7DOKwCmR8qIhsGpBRBuztzHups2joQa4RTihC
11
+ 7hmdGz2VLFR0J9xphLV57W/ObJuxTD3sqL3HrsDkfv6Poi6iS1GBFtDUuxrFtUv/
12
+ K1Yao02gkXD32Mq5M38uTyBK7nEhS1V7cvP0iHPdLgan9bsrOREXyVV+u0gr2IN1
13
+ wKvyYs0CgYEA7HiL3JdOwlxzWznHLRPOd07cOnwkq5eauqmT2nzxtqL3InSFmNtL
14
+ 1hMfIRA2wejo/Q1Ezi7d7RCHsSHBfCGag7L/NdVnIiHAErbVf+LofvjL2C9LShKB
15
+ u4DxPsb7hcj3I9qaHoc0zotxjAkg38sdr2sfP7EMc5k+asPb9MA/bX8CgYEAzP7z
16
+ J4c+CkUhUg1xynZswjxvvC3oMhbC2vVsuKt/ZMwFolpDvVJNcrFOFkqikaGDLcPB
17
+ Dg2WxxZdujnfXBWjTI8M7pfhD1u2OW99yQsWxnWOc1C4n4OjPH0/sn9IEAjlmTpc
18
+ 5NYZB6dAARGRTEJN8srNGm59z0S6jLyciuErS18CgYBk8lz6cVk83YydMAAX/TGR
19
+ ewfGq8JXwiNadhPZHKdvCQipG8cAZvVr0MPkMHC/vLbhd+2ceyNgFUNn2XoojIvS
20
+ lvIdwBkD2BaPpp9jtbD8qycSBbaFS3s4WSYjX3x2M0FVe/d4+s0PMzXoyujOwH3O
21
+ qdMwNFuVaaDcoPnf9MXe7wKBgH9OpbsaplDCddr7NnvB5/EIj2uSJu1UbVaFrCtT
22
+ dh4nBii5XfApOKfNrOzzFNrULx8wvqf3kHe7UCHi5u/NEEjvXdyevcpH7nbk4n0E
23
+ QfSl9P1wV/fYTHu4XOKBYUN0AwKR2DbVL14tY/ZF7rIpSzdI8u9DRyZ9TE0ypRUq
24
+ mTSJAoGAOkzZ2D/nQyIz9mHOKmDoXWbFgZ32rqTzqfS07cq5vtt2Ol2MTRXY386Q
25
+ kW1AyHf0hz8SQe3+An4K6uMpGkZ6dzEOXhsw1+fwU9jFb+qucRuhTVlyVWDVtkf6
26
+ NRg6ZlSfTi3KxmaSsY7X/t9DfWmud8MXTm3cUqI0VdljQmAT85A=
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,48 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDjzCCAnegAwIBAgIJAP/ZxwuHN9GUMA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNV
3
+ BAYTAlVTMREwDwYDVQQIDAhJbGxpbm9pczEQMA4GA1UEBwwHQ2hpY2FnbzEYMBYG
4
+ A1UECgwPUnVieSBDQSBQcm9qZWN0MRAwDgYDVQQDDAdUZXN0IENBMB4XDTExMDIy
5
+ MDIwNDkxMloXDTMwMDQyMTIwNDkxMlowXjELMAkGA1UEBhMCVVMxETAPBgNVBAgM
6
+ CElsbGlub2lzMRAwDgYDVQQHDAdDaGljYWdvMRgwFgYDVQQKDA9SdWJ5IENBIFBy
7
+ b2plY3QxEDAOBgNVBAMMB1Rlc3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
8
+ ggEKAoIBAQCot8/z3jxARkwyRk0csM84dlWs91W95wPpunx3P3otqUxCJaOAyQl/
9
+ uY8deg0xDmsime2JQ6aG6m76y3LfT4J1tlkhtmiGKhNJir1kgL8sL0wTXYXvwZEw
10
+ qEEYD5mKi7Na9eo4R0ydqd9KAquVIhKywXvV1+Y4RDTx+f1WXmMCBaYZ76/rXmIe
11
+ oE0avriRiihOtlgto+VNJw7VRnvq+cEd81BT62wRk1fG1lcpCqTEfEtKEI6PqqZh
12
+ E2f+6lNmhZZ3Tj7NeNgYQLd4q+L1y030Vj4onpAIJrwfQq3dxTmrLDqnN2WOFsbo
13
+ 0qGh3s4yqUaOYd2wIBgCp7fEf5X/yh53AgMBAAGjUDBOMB0GA1UdDgQWBBR5dbuE
14
+ Osss3noJvjEbQ7wcKk1TWDAfBgNVHSMEGDAWgBR5dbuEOsss3noJvjEbQ7wcKk1T
15
+ WDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAp/Fh+WWjN7x/SZzMm
16
+ H1INAS4loufHXzkqI+3bClAzlhzpBVbY7dHwD6H8oKh06EtppbN0Bw3iqXSRyoNd
17
+ +lDXccPij5dCuTFQ97DOrv7kGlhiM95XVkx4mvnd+i6jKwgOpllgDE/nKOwC42bq
18
+ lIikcp7XLQUPt7amyX9UeJ8lxQ/niSkT868ls2IZQkF3XEhCi+5VlefEoaiMQZmD
19
+ RyEd/vlsSnpXI5LLpkFq+NFGvgdI7+UADNIyDplyivD4VyQ6+zisX3r1ojroa6Y+
20
+ WyXxLx+AVJVnGjngr2fDKr4ggsYWlJEs8lJ0r90jliYrSPA6rIldTbs3k9AbUp8G
21
+ kS6X
22
+ -----END CERTIFICATE-----
23
+ -----BEGIN CERTIFICATE-----
24
+ MIIEaDCCA1CgAwIBAgIVAOpjrhBj/knK4IwIzIpSmDxdBlOYMA0GCSqGSIb3DQEB
25
+ BQUAMF4xCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhJbGxpbm9pczEQMA4GA1UEBwwH
26
+ Q2hpY2FnbzEYMBYGA1UECgwPUnVieSBDQSBQcm9qZWN0MRAwDgYDVQQDDAdUZXN0
27
+ IENBMB4XDTExMTIxNjA5NTg1NloXDTEyMTIxNTA5NTg1NlowGzEZMBcGA1UEAwwQ
28
+ cjUwOSBPQ1NQIFNpZ25lcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
29
+ ALVK9XwIRznpBNC7Ltqqq4RSrkGdRZzt3fI2MrJVYAz1fc+kZ8IfsmEiZxGgRuQ2
30
+ 83TNF70IsSR6a3oiPUKuywqDbKBaXNDMzhLJKvT1bHsIfkBQ//IYKtN9JCBLzs92
31
+ vcsV5hZOhTs0WDyKvmjdX3Xh8vKtMoX1pfSjuXQuTpzTiQW/LDlfnDy5Cf668D1K
32
+ JsaEd8Nd4xncpWTj806WyODAkkqEaIvJJ014itqy9Tjo+m9TxGmRrY6SaBJRQGGe
33
+ Z6e0s6eccYuGrdFyElXc2M5kWkKirTmCSPGGokx9vw8v1EcdvNFlW2pug31RFWt9
34
+ sZ5P6XVkMykwjJwMyPm93dMCAwEAAaOCAV4wggFaMAwGA1UdEwEB/wQCMAAwHQYD
35
+ VR0OBBYEFCgE62q6is5xpdlkkPU1zy93piH2MAsGA1UdDwQEAwIHgDCBkAYDVR0j
36
+ BIGIMIGFgBR5dbuEOsss3noJvjEbQ7wcKk1TWKFipGAwXjELMAkGA1UEBhMCVVMx
37
+ ETAPBgNVBAgMCElsbGlub2lzMRAwDgYDVQQHDAdDaGljYWdvMRgwFgYDVQQKDA9S
38
+ dWJ5IENBIFByb2plY3QxEDAOBgNVBAMMB1Rlc3QgQ0GCCQD/2ccLhzfRlDATBgNV
39
+ HSUEDDAKBggrBgEFBQcDCTAOBgNVHSAEBzAFMAMGAQAwMgYDVR0fBCswKTAnoCWg
40
+ I4YhaHR0cDovL2NybC5kb21haW4uY29tL3Rlc3RfY2EuY3JsMDIGCCsGAQUFBwEB
41
+ BCYwJDAiBggrBgEFBQcwAYYWaHR0cDovL29jc3AuZG9tYWluLmNvbTANBgkqhkiG
42
+ 9w0BAQUFAAOCAQEADNAMfwzRpx8UoWe1i/qivAIPJtP2zlop0eIwSy9ocAoAfcHF
43
+ wVsdBzIb74amm4z/+y7j4x8ZAY2d4hosdDH05OKnGVHUT0ASzYjh0zDgOItObk2L
44
+ XrMykW2GCNGTOlt1C/FfKVkBMDQz7Pi8fXmHsI4N1A0krTEVgVwKVLn0TrrLZ6OP
45
+ 0vsj9nqSPYJ4eLsIE3gp4RBLJWGtLWtlkIwKLU/ZhpKo7VcvoZU8zDjHJR/HO9uD
46
+ T3vlekoEc5rlWk9Uobh9Sz/pFb/r/ErOkXBnka1XunJQBOLe6wj1T2v/B0zMv6RG
47
+ Tpd0n0zKik4a7nBH82jxg78kRLUfjbhFZienKA==
48
+ -----END CERTIFICATE-----
@@ -0,0 +1,25 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEJjCCAw6gAwIBAgIVALxHSa9L48ZH3q9EANuGMICYOmRpMA0GCSqGSIb3DQEB
3
+ BQUAMF4xCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhJbGxpbm9pczEQMA4GA1UEBwwH
4
+ Q2hpY2FnbzEYMBYGA1UECgwPUnVieSBDQSBQcm9qZWN0MRAwDgYDVQQDDAdUZXN0
5
+ IENBMB4XDTEyMDEwNjExNTQxOVoXDTMyMDEwMTE3NTQxOVowLjELMAkGA1UEBhMC
6
+ VVMxHzAdBgNVBAMMFnI1MDkgQXJiaXRyYXJ5IFN1YnJvb3QwggEiMA0GCSqGSIb3
7
+ DQEBAQUAA4IBDwAwggEKAoIBAQC6s6E0RHPdC/g6ZVe/4bRka2FndjqCwxiuTpaq
8
+ FQwf8/etXyCuz0ZADs04WaqCtIs+uUoXh+jSBg0BVC0rc1pCoQIraq9M3ZJ1umu/
9
+ i96Ohhjbk1ygJW3U1+vdxWuowk4H51/pLbNUIy/fntSTE1vSbVo1rviK/SFXpHT3
10
+ PaPjIX4IjLpnW12+h1zH5P9yLoIZ/NN+s64rW21JX3y/gFG4DW9d0LxMKbI5Nixv
11
+ bn+1mpLCcPn+pO4i/8o8AXs/FsoKing32m23k7+8rz2IWKZWcVoLe4/x+j00zzjv
12
+ eXAvvoXBomYgftsj83tCQ5vOFznVoZJROfqKtcRwFpDaQosBAgMBAAGjggEJMIIB
13
+ BTASBgNVHRMBAf8ECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUtsRD
14
+ bNCYQJnEYNRxJAcAcPZ6JWowgZAGA1UdIwSBiDCBhYAUeXW7hDrLLN56Cb4xG0O8
15
+ HCpNU1ihYqRgMF4xCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhJbGxpbm9pczEQMA4G
16
+ A1UEBwwHQ2hpY2FnbzEYMBYGA1UECgwPUnVieSBDQSBQcm9qZWN0MRAwDgYDVQQD
17
+ DAdUZXN0IENBggkA/9nHC4c30ZQwMAYIKwYBBQUHAQEEJDAiMCAGCCsGAQUFBzAB
18
+ hhRodHRwOi8vb2NzcC5yNTA5Lm9yZzANBgkqhkiG9w0BAQUFAAOCAQEAAV6ub5mP
19
+ xLYV8Zpu6WhG1JvM8PKEUzPv5jR3Bzm0MG9ISlT9soVO2LxcRoRUMscTzvPLIIj/
20
+ R24fMjJMzewu/BmYVcJJ9aG1z5Zdlczjz+Jm8P40V1x6iMn/MZrDc4Yx00TIkzT0
21
+ b2w6GvPjS6RZwybTr6d1bj8EB0Urbuk7a/FL3hOi5wQ4AWh+RqW8mWjvjs1ElKE5
22
+ hpIb2fjC3JnifZAo/sD2xV8Y3Vasqb2uUGYZ3+HZFTbF+WQ6OZHVHlv0xB1yYTid
23
+ 4melkAZEPf5OblurgioGu0b9nSHGdrCrk84nKdNN3w5rFOPo/dyaO5wcYIpcpC6f
24
+ Hs6C1rY6pPOImw==
25
+ -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEogIBAAKCAQEAurOhNERz3Qv4OmVXv+G0ZGthZ3Y6gsMYrk6WqhUMH/P3rV8g
3
+ rs9GQA7NOFmqgrSLPrlKF4fo0gYNAVQtK3NaQqECK2qvTN2Sdbprv4vejoYY25Nc
4
+ oCVt1Nfr3cVrqMJOB+df6S2zVCMv357UkxNb0m1aNa74iv0hV6R09z2j4yF+CIy6
5
+ Z1tdvodcx+T/ci6CGfzTfrOuK1ttSV98v4BRuA1vXdC8TCmyOTYsb25/tZqSwnD5
6
+ /qTuIv/KPAF7PxbKCop4N9ptt5O/vK89iFimVnFaC3uP8fo9NM8473lwL76FwaJm
7
+ IH7bI/N7QkObzhc51aGSUTn6irXEcBaQ2kKLAQIDAQABAoIBAGjoMGenIxeM90EQ
8
+ 2tq132AhukyhcUUyjPa8sAoH45U8x+oCLuIrE8VAy+2i7J2fBzMKeGh6dMc2oS4i
9
+ 93KX0Zroz8hHnRLq2bYPNyYdWMPq86LFzeEqxuk3HpCxssnTzHbCevESPdbEIs1b
10
+ eQTfdtPpoCvUElI+4/JUNWkLmMAxhlnQjAVIIB4RsjUugn4h2VZIj5tx7L9at06C
11
+ TPz10xA6v+uIxtYE1Ijr0LB0LjV7FIttfHbq/6SoNaRCGYz1m0VN6CJ/cN6tBMAj
12
+ EKwpnfD1kr0T1N+Y27lnLEW+xSg8DfQIchaKc3dJFr8Sx+WbpajSKEywtfl4wpTV
13
+ iwT/ZDECgYEA6dqXr038bf29womMh9Qds2YMUt5SI+SjA9DHxcvodCzyG5dvchpY
14
+ 0V8RXPWJsVV9ECWbGr8T0ZPPXo3EFR8JyOUBDnDgDE0SlhFo4lNlRLHYFsUPrjgf
15
+ 6IHhCTtkZtdOr7ObZe4mOjo3K2tQcN7e4uArIFqNP5tUc48hcNhO410CgYEAzGHo
16
+ oOsj7xBBO+3ohIsXgXXlNqcAnCBkUYVC9HIBi+atWUddpsXrXF+YVMn3Kw8nEZnE
17
+ /KUINnwn+NyInmSEmgRuWo6Uv+dxa8I7H51LkjtmhhIFkMTxXewTLdrWkX1M/9dp
18
+ RwrkGHN3vTYPi4/PT18FIw/MZ6pH9ly4M1Kqj/UCgYBUAC4eTWAQTmX8XBY7sCjf
19
+ CRgCKFPPCtC3jSZFWYJtQLvSx2nDzcz7oC+Hebd1GKUsyKVXTS2cSYDikP/PKnAE
20
+ VqYzfr4sDP9RIn3PVm945n0daLnCNezYQtcHzuq4ujxMhrKaQZo/riulEA48DQJ4
21
+ 8lbrbztvjqceP1qew0RLDQKBgGBqy/imFSShcXTZLjjg+SzMtl5K+IGu0kSW7lgt
22
+ NEeQgjS88xRLCFZijpVpVd4NXuvxs7lQDYjOl3jSaOz4FIooDvtPiiLiB2LDlWq7
23
+ pLwOo7YZ6GA8WHVrejzGoTSvfNSxBWxLWgGi71jmmPzI0g7qj5zTxiUdcqdpZEhp
24
+ 9ibFAoGAPMEI59/eCmSZPIZ7acs//4HI0QTo6856KZj4bqlowdeZf/D7uyCpn7UX
25
+ 904L4tAVwLKddqmDXbReS/ObsNs4v1FsdgnTySR59PYmW67S/CMzyN0T9Ld4xtOe
26
+ R/khjaviCkqAmPzDRx8+OZmbzNJtb0s6hJIQS73lcj84kuprSio=
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,25 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEPzCCAyegAwIBAgIVAPVJ8f7HkMe36qArq2sTN1abDCjWMA0GCSqGSIb3DQEB
3
+ BQUAMC4xCzAJBgNVBAYTAlVTMR8wHQYDVQQDDBZyNTA5IEFyYml0cmFyeSBTdWJy
4
+ b290MB4XDTEyMDEwNjEzMDgzNFoXDTMyMDEwMTE5MDgzNFowaDELMAkGA1UEBhMC
5
+ VVMxETAPBgNVBAgMCElsbGlub2lzMRAwDgYDVQQHDAdDaGljYWdvMREwDwYDVQQK
6
+ DAhyNTA5IExMQzEhMB8GA1UEAwwYcjUwOSBTdWJyb290IE9DU1AgU2lnbmVyMIIB
7
+ IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuOPd0oz5t/GJyB94jTXyALy7
8
+ tD2F3FgIIkMx+0zWwxytd7OMWmYGnxxSjx/kC1VbLnB254llbWVf6aZO13sNgXTb
9
+ tXtWcHBSIfje1IAFW85+UHuQ3L/cv/JoFxFL0r0L/MPO0zwMTBa68TVTS6LhvjNY
10
+ 8mK0Oot6i/m/Hh7LXK6ynYxqqacAdK6PKMKsGG1ywDwrGNvjLpH3qmzTkqTkF+8o
11
+ J2B5kgIAMVEfgiK46zFtIMe6tcDT7n5KJ2NwG3GVwRnrTgnuBqpp8/hukAEdLT/L
12
+ yD0DShA5HWljJQGj8JlWe+x2k68kMHN4fgNfBoE97wjFCdeolKSHUP6yDn3+wQID
13
+ AQABo4IBGDCCARQwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDCTAd
14
+ BgNVHQ4EFgQU0sNGTKxh+UEPYyBk1Wi3Uisq4gkwgZwGA1UdIwSBlDCBkYAUtsRD
15
+ bNCYQJnEYNRxJAcAcPZ6JWqhYqRgMF4xCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhJ
16
+ bGxpbm9pczEQMA4GA1UEBwwHQ2hpY2FnbzEYMBYGA1UECgwPUnVieSBDQSBQcm9q
17
+ ZWN0MRAwDgYDVQQDDAdUZXN0IENBghUAvEdJr0vjxkfer0QA24YwgJg6ZGkwMQYI
18
+ KwYBBQUHAQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vb2NzcC5yNTA5Lm9yZy8w
19
+ DQYJKoZIhvcNAQEFBQADggEBALOUPqx9blxSYAvor/H1ITWz0huj+WPvGdPQABGn
20
+ nu16V7Jak3EposqXY9ObKteWzdiLvo41O4mVAviBhdKYexo/LLlEa5cP6/lRQ2yC
21
+ TR5MKYTVIaaSuxCTxwM4AF2XFaRs2AnxcpPKQjCkxe6fT0lPwuQbBdQqjtRl39CR
22
+ +2muSQlqpCz4KTPivTOCyOizIrhnxhMjcSr1zxpEPsCbJO0Bd/8PPHPER3MMXmYb
23
+ Ci3HVRWqDczVniy3tmKh20rEWZPUmJNiLaGLdD5Ug39YhGMn9fkT+x8+UxIeaNZW
24
+ 2JtcNoOp9v5e7EOcxJp2doHq3+FCOii3LwHlwk2XMAeKYKo=
25
+ -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEpAIBAAKCAQEAuOPd0oz5t/GJyB94jTXyALy7tD2F3FgIIkMx+0zWwxytd7OM
3
+ WmYGnxxSjx/kC1VbLnB254llbWVf6aZO13sNgXTbtXtWcHBSIfje1IAFW85+UHuQ
4
+ 3L/cv/JoFxFL0r0L/MPO0zwMTBa68TVTS6LhvjNY8mK0Oot6i/m/Hh7LXK6ynYxq
5
+ qacAdK6PKMKsGG1ywDwrGNvjLpH3qmzTkqTkF+8oJ2B5kgIAMVEfgiK46zFtIMe6
6
+ tcDT7n5KJ2NwG3GVwRnrTgnuBqpp8/hukAEdLT/LyD0DShA5HWljJQGj8JlWe+x2
7
+ k68kMHN4fgNfBoE97wjFCdeolKSHUP6yDn3+wQIDAQABAoIBAEql1X2Y5Ynav2JJ
8
+ Mobw7NBXYwGWhWE9Oat7rcZkc6E7Bt55Y4VsA+hhqwOWQKBCyhmp1pgM5SKR93OC
9
+ bfqZ+A34fGx9a5zh/Icyz+TD+2XhrSYZfZdi72GgIV6O4SoooZpgBDVM3TorQzb3
10
+ 7LVxAeulF5hlOZcZkVTKdNtYW4sDXa0zthSLhCladQjRSV2znuNN1ZRocQhNRMv6
11
+ 4MgOVon2S22HkxFHz0yT6NImp6Ns3Qvjoej1MAcuhMhcHFFvhHvn1GUF4Ur6A6JP
12
+ Rbr2Z6h0hUmKqVX02kEgYhJduy3btVr+QGKDZBD43vzFZ74ZQsLbK9mXZFU0eOe9
13
+ dWglZ0ECgYEA5i2saggVyHbOm+WbE5FvUwVrkdokM9lUeK6QY+mWN0xJ8uTUwplR
14
+ iXw4gr7Jcl5D8SoNm6EFGzQh4ZVkZw8v0CpO18sA3gTBVLMPl8EijUzUNk6MIKUL
15
+ h37O0Wr6hnpFsuTwFZgwmuBc4KYY9eNVhzURjDD+bbvNx+9krYLuU3UCgYEAzaGX
16
+ StD/d8ypcAmzl0x4BeN7QbkHRtYC5MqPfkycmegypJAIXIV9kVRGznj4+Q2Zne9e
17
+ E1llS41KJHgi04LL34/wunSAPGNTLEbhQObSxZppDTFmZhouN4CMEIUMrETXHDri
18
+ Qy0SMLmnD3LxmpnGvMMyQICU1BfLvIPxvUh3kJ0CgYATohWwvZvOC4Q3+++sTZ1n
19
+ QXEZcbfgzErOOGWMgCIV+WXdV/Nl3dn8liHj1Q4tuSima2XZvnRHC71QFoQH3l2/
20
+ rbwn3+LlDRbIeLV9xjWCQ+ld8Hk3V5ySJBjT+AICcm97gNeRn/eVXknNx50dbBSh
21
+ gb9La+pnxbsZsKuvuRlG+QKBgQC8U8ByXxN6LtEHsXrvmLNcAUmDmehWMe8Yh4QA
22
+ Ej5insyy9s8RnZixH1RyCU1NG+2TPgUVB4zEMzSyTezndiUuLXA19Dj2Fam5JXlr
23
+ rXtgStjnolS8MkIdxveAsbo3lBzG2A8dowvD4GRmu8kW5Lulach+VsT3sot/rgAa
24
+ cWI/6QKBgQCWL6c25xjU71n+ZQfXt1nLes1Z06bs25oOJnY6cKwXn41o4Z+FAaEG
25
+ +XSpGDHed5lO/WqolSMF1BGAVgZU6x7YK0iBDbRia5bVs3KAs0p7vEO2vIKNx58A
26
+ UuuAb6igKKOLzM7L7vzNwQr4QyuSUTL0cgOlVT6RVR1F6tlkXd2wdw==
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,17 @@
1
+ copy_nonce: true
2
+ cache_headers: true
3
+ max_cache_age: 60
4
+ certificate_authorities: {
5
+ test_ca: {
6
+ ca_cert: {
7
+ cert: "spec/fixtures/test_ca.cer",
8
+ key: "spec/fixtures/test_ca.key"
9
+ }
10
+ },
11
+ second_ca: {
12
+ ca_cert: {
13
+ cert: "spec/fixtures/second_ca.cer",
14
+ key: "spec/fixtures/second_ca.key"
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,400 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
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
400
+ end