revoke_test.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. package revoke
  2. import (
  3. "crypto/x509"
  4. // "crypto/x509/pkix"
  5. "encoding/pem"
  6. "fmt"
  7. "os"
  8. "testing"
  9. "time"
  10. )
  11. // The first three test cases represent known revoked, expired, and good
  12. // certificates that were checked on the date listed in the log. The
  13. // good certificate will eventually need to be replaced in year 2029.
  14. // If there is a soft-fail, the test will pass to mimic the default
  15. // behaviour used in this software. However, it will print a warning
  16. // to indicate that this is the case.
  17. // 2014/05/22 14:18:17 Certificate expired 2014-04-04 14:14:20 +0000 UTC
  18. // 2014/05/22 14:18:17 Revoked certificate: misc/intermediate_ca/ActalisServerAuthenticationCA.crt
  19. var expiredCert = mustParse(`-----BEGIN CERTIFICATE-----
  20. MIIEXTCCA8agAwIBAgIEBycURTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV
  21. UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
  22. cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds
  23. b2JhbCBSb290MB4XDTA3MDQwNDE0MTUxNFoXDTE0MDQwNDE0MTQyMFowejELMAkG
  24. A1UEBhMCSVQxFzAVBgNVBAoTDkFjdGFsaXMgUy5wLkEuMScwJQYDVQQLEx5DZXJ0
  25. aWZpY2F0aW9uIFNlcnZpY2UgUHJvdmlkZXIxKTAnBgNVBAMTIEFjdGFsaXMgU2Vy
  26. dmVyIEF1dGhlbnRpY2F0aW9uIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
  27. CgKCAQEAv6P0bhXbUQkVW8ox0HJ+sP5+j6pTwS7yg/wGEUektB/G1duQiT1v21fo
  28. LANr6F353jILQDCpHIfal3MhbSsHEMKU7XaqsyLWV93bcIKbIloS/eXDfkog6KB3
  29. u0JHgrtNz584Jg/OLm9feffNbCJ38TiLo0/UWkAQ6PQWaOwZEgyKjVI5F3swoTB3
  30. g0LZAzegvkU00Kfp13cSg+cJeU4SajwtfQ+g6s6dlaekaHy/0ef46PfiHHRuhEhE
  31. JWIpDtUN2ywTT33MSSUe5glDIiXYfcamJQrebzGsHEwyqI195Yaxb+FLNND4n3HM
  32. e7EI2OrLyT+r/WMvQbl+xNihwtv+HwIDAQABo4IBbzCCAWswEgYDVR0TAQH/BAgw
  33. BgEB/wIBADBTBgNVHSAETDBKMEgGCSsGAQQBsT4BADA7MDkGCCsGAQUFBwIBFi1o
  34. dHRwOi8vd3d3LnB1YmxpYy10cnVzdC5jb20vQ1BTL09tbmlSb290Lmh0bWwwDgYD
  35. VR0PAQH/BAQDAgEGMIGJBgNVHSMEgYEwf6F5pHcwdTELMAkGA1UEBhMCVVMxGDAW
  36. BgNVBAoTD0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3Qg
  37. U29sdXRpb25zLCBJbmMuMSMwIQYDVQQDExpHVEUgQ3liZXJUcnVzdCBHbG9iYWwg
  38. Um9vdIICAaUwRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL3d3dy5wdWJsaWMtdHJ1
  39. c3QuY29tL2NnaS1iaW4vQ1JMLzIwMTgvY2RwLmNybDAdBgNVHQ4EFgQUpi6OuXYt
  40. oxHC3cTezVLuraWpAFEwDQYJKoZIhvcNAQEFBQADgYEAAtjJBwjsvw7DBs+v7BQz
  41. gSGeg6nbYUuPL7+1driT5XsUKJ7WZjiwW2zW/WHZ+zGo1Ev8Dc574RpSrg/EIlfH
  42. TpBiBuFgiKtJksKdoxPZGSI8FitwcgeW+y8wotmm0CtDzWN27g2kfSqHb5eHfZY5
  43. sESPRwHkcMUNdAp37FLweUw=
  44. -----END CERTIFICATE-----`)
  45. // 2014/05/22 14:18:31 Serial number match: intermediate is revoked.
  46. // 2014/05/22 14:18:31 certificate is revoked via CRL
  47. // 2014/05/22 14:18:31 Revoked certificate: misc/intermediate_ca/MobileArmorEnterpriseCA.crt
  48. var revokedCert = mustParse(`-----BEGIN CERTIFICATE-----
  49. MIIEEzCCAvugAwIBAgILBAAAAAABGMGjftYwDQYJKoZIhvcNAQEFBQAwcTEoMCYG
  50. A1UEAxMfR2xvYmFsU2lnbiBSb290U2lnbiBQYXJ0bmVycyBDQTEdMBsGA1UECxMU
  51. Um9vdFNpZ24gUGFydG5lcnMgQ0ExGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex
  52. CzAJBgNVBAYTAkJFMB4XDTA4MDMxODEyMDAwMFoXDTE4MDMxODEyMDAwMFowJTEj
  53. MCEGA1UEAxMaTW9iaWxlIEFybW9yIEVudGVycHJpc2UgQ0EwggEiMA0GCSqGSIb3
  54. DQEBAQUAA4IBDwAwggEKAoIBAQCaEjeDR73jSZVlacRn5bc5VIPdyouHvGIBUxyS
  55. C6483HgoDlWrWlkEndUYFjRPiQqJFthdJxfglykXD+btHixMIYbz/6eb7hRTdT9w
  56. HKsfH+wTBIdb5AZiNjkg3QcCET5HfanJhpREjZWP513jM/GSrG3VwD6X5yttCIH1
  57. NFTDAr7aqpW/UPw4gcPfkwS92HPdIkb2DYnsqRrnKyNValVItkxJiotQ1HOO3YfX
  58. ivGrHIbJdWYg0rZnkPOgYF0d+aIA4ZfwvdW48+r/cxvLevieuKj5CTBZZ8XrFt8r
  59. JTZhZljbZvnvq/t6ZIzlwOj082f+lTssr1fJ3JsIPnG2lmgTAgMBAAGjgfcwgfQw
  60. DgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFIZw
  61. ns4uzXdLX6xDRXUzFgZxWM7oME0GA1UdIARGMEQwQgYJKwYBBAGgMgE8MDUwMwYI
  62. KwYBBQUHAgIwJxolaHR0cDovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5
  63. LzA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmdsb2JhbHNpZ24ubmV0L1Jv
  64. b3RTaWduUGFydG5lcnMuY3JsMB8GA1UdIwQYMBaAFFaE7LVxpedj2NtRBNb65vBI
  65. UknOMA0GCSqGSIb3DQEBBQUAA4IBAQBZvf+2xUJE0ekxuNk30kPDj+5u9oI3jZyM
  66. wvhKcs7AuRAbcxPtSOnVGNYl8By7DPvPun+U3Yci8540y143RgD+kz3jxIBaoW/o
  67. c4+X61v6DBUtcBPEt+KkV6HIsZ61SZmc/Y1I2eoeEt6JYoLjEZMDLLvc1cK/+wpg
  68. dUZSK4O9kjvIXqvsqIOlkmh/6puSugTNao2A7EIQr8ut0ZmzKzMyZ0BuQhJDnAPd
  69. Kz5vh+5tmytUPKA8hUgmLWe94lMb7Uqq2wgZKsqun5DAWleKu81w7wEcOrjiiB+x
  70. jeBHq7OnpWm+ccTOPCE6H4ZN4wWVS7biEBUdop/8HgXBPQHWAdjL
  71. -----END CERTIFICATE-----`)
  72. // A Comodo intermediate CA certificate with issuer url, CRL url and OCSP url
  73. var goodComodoCA = (`-----BEGIN CERTIFICATE-----
  74. MIIGCDCCA/CgAwIBAgIQKy5u6tl1NmwUim7bo3yMBzANBgkqhkiG9w0BAQwFADCB
  75. hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
  76. A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
  77. BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwMjEy
  78. MDAwMDAwWhcNMjkwMjExMjM1OTU5WjCBkDELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
  79. EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
  80. Q09NT0RPIENBIExpbWl0ZWQxNjA0BgNVBAMTLUNPTU9ETyBSU0EgRG9tYWluIFZh
  81. bGlkYXRpb24gU2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
  82. ADCCAQoCggEBAI7CAhnhoFmk6zg1jSz9AdDTScBkxwtiBUUWOqigwAwCfx3M28Sh
  83. bXcDow+G+eMGnD4LgYqbSRutA776S9uMIO3Vzl5ljj4Nr0zCsLdFXlIvNN5IJGS0
  84. Qa4Al/e+Z96e0HqnU4A7fK31llVvl0cKfIWLIpeNs4TgllfQcBhglo/uLQeTnaG6
  85. ytHNe+nEKpooIZFNb5JPJaXyejXdJtxGpdCsWTWM/06RQ1A/WZMebFEh7lgUq/51
  86. UHg+TLAchhP6a5i84DuUHoVS3AOTJBhuyydRReZw3iVDpA3hSqXttn7IzW3uLh0n
  87. c13cRTCAquOyQQuvvUSH2rnlG51/ruWFgqUCAwEAAaOCAWUwggFhMB8GA1UdIwQY
  88. MBaAFLuvfgI9+qbxPISOre44mOzZMjLUMB0GA1UdDgQWBBSQr2o6lFoL2JDqElZz
  89. 30O0Oija5zAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNV
  90. HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgG
  91. BmeBDAECATBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNv
  92. bS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggrBgEFBQcB
  93. AQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9E
  94. T1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21v
  95. ZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAE4rdk+SHGI2ibp3wScF9BzWRJ2p
  96. mj6q1WZmAT7qSeaiNbz69t2Vjpk1mA42GHWx3d1Qcnyu3HeIzg/3kCDKo2cuH1Z/
  97. e+FE6kKVxF0NAVBGFfKBiVlsit2M8RKhjTpCipj4SzR7JzsItG8kO3KdY3RYPBps
  98. P0/HEZrIqPW1N+8QRcZs2eBelSaz662jue5/DJpmNXMyYE7l3YphLG5SEXdoltMY
  99. dVEVABt0iN3hxzgEQyjpFv3ZBdRdRydg1vs4O2xyopT4Qhrf7W8GjEXCBgCq5Ojc
  100. 2bXhc3js9iPc0d1sjhqPpepUfJa3w/5Vjo1JXvxku88+vZbrac2/4EjxYoIQ5QxG
  101. V/Iz2tDIY+3GH5QFlkoakdH368+PUq4NCNk+qKBR6cGHdNXJ93SrLlP7u3r7l+L4
  102. HyaPs9Kg4DdbKDsx5Q5XLVq4rXmsXiBmGqW5prU5wfWYQ//u+aen/e7KJD2AFsQX
  103. j4rBYKEMrltDR5FL1ZoXX/nUh8HCjLfn4g8wGTeGrODcQgPmlKidrv0PJFGUzpII
  104. 0fxQ8ANAe4hZ7Q7drNJ3gjTcBpUC2JD5Leo31Rpg0Gcg19hCC0Wvgmje3WYkN5Ap
  105. lBlGGSW4gNfL1IYoakRwJiNiqZ+Gb7+6kHDSVneFeO/qJakXzlByjAA6quPbYzSf
  106. +AZxAeKCINT+b72x
  107. -----END CERTIFICATE-----`)
  108. var goodCert = mustParse(goodComodoCA)
  109. func mustParse(pemData string) *x509.Certificate {
  110. block, _ := pem.Decode([]byte(pemData))
  111. if block == nil {
  112. panic("Invalid PEM data.")
  113. } else if block.Type != "CERTIFICATE" {
  114. panic("Invalid PEM type.")
  115. }
  116. cert, err := x509.ParseCertificate([]byte(block.Bytes))
  117. if err != nil {
  118. panic(err.Error())
  119. }
  120. return cert
  121. }
  122. func TestRevoked(t *testing.T) {
  123. if revoked, ok := VerifyCertificate(revokedCert); !ok {
  124. fmt.Fprintf(os.Stderr, "Warning: soft fail checking revocation")
  125. } else if !revoked {
  126. t.Fatalf("revoked certificate should have been marked as revoked")
  127. }
  128. }
  129. func TestExpired(t *testing.T) {
  130. if revoked, ok := VerifyCertificate(expiredCert); !ok {
  131. fmt.Fprintf(os.Stderr, "Warning: soft fail checking revocation")
  132. } else if !revoked {
  133. t.Fatalf("expired certificate should have been marked as revoked")
  134. }
  135. }
  136. func TestGood(t *testing.T) {
  137. if revoked, ok := VerifyCertificate(goodCert); !ok {
  138. fmt.Fprintf(os.Stderr, "Warning: soft fail checking revocation")
  139. } else if revoked {
  140. t.Fatalf("good certificate should not have been marked as revoked")
  141. }
  142. }
  143. func TestLdap(t *testing.T) {
  144. ldapCert := mustParse(goodComodoCA)
  145. ldapCert.CRLDistributionPoints = append(ldapCert.CRLDistributionPoints, "ldap://myldap.example.com")
  146. if revoked, ok := VerifyCertificate(ldapCert); revoked || !ok {
  147. t.Fatalf("ldap certificate should have been recognized")
  148. }
  149. }
  150. func TestLdapURLErr(t *testing.T) {
  151. if ldapURL(":") {
  152. t.Fatalf("bad url does not cause error")
  153. }
  154. }
  155. func TestCertNotYetValid(t *testing.T) {
  156. notReadyCert := expiredCert
  157. notReadyCert.NotBefore = time.Date(3000, time.January, 1, 1, 1, 1, 1, time.Local)
  158. notReadyCert.NotAfter = time.Date(3005, time.January, 1, 1, 1, 1, 1, time.Local)
  159. if revoked, _ := VerifyCertificate(expiredCert); !revoked {
  160. t.Fatalf("not yet verified certificate should have been marked as revoked")
  161. }
  162. }
  163. func TestCRLFetchError(t *testing.T) {
  164. ldapCert := mustParse(goodComodoCA)
  165. ldapCert.CRLDistributionPoints[0] = ""
  166. if revoked, ok := VerifyCertificate(ldapCert); ok || revoked {
  167. t.Fatalf("Fetching error not encountered")
  168. }
  169. HardFail = true
  170. if revoked, ok := VerifyCertificate(ldapCert); ok || !revoked {
  171. t.Fatalf("Fetching error not encountered, hardfail not registered")
  172. }
  173. HardFail = false
  174. }
  175. func TestBadCRLSet(t *testing.T) {
  176. ldapCert := mustParse(goodComodoCA)
  177. ldapCert.CRLDistributionPoints[0] = ""
  178. CRLSet[""] = nil
  179. certIsRevokedCRL(ldapCert, "")
  180. if _, ok := CRLSet[""]; ok {
  181. t.Fatalf("key emptystring should be deleted from CRLSet")
  182. }
  183. delete(CRLSet, "")
  184. }
  185. func TestCachedCRLSet(t *testing.T) {
  186. VerifyCertificate(goodCert)
  187. if revoked, ok := VerifyCertificate(goodCert); !ok || revoked {
  188. t.Fatalf("Previously fetched CRL's should be read smoothly and unrevoked")
  189. }
  190. }
  191. func TestRemoteFetchError(t *testing.T) {
  192. badurl := ":"
  193. if _, err := fetchRemote(badurl); err == nil {
  194. t.Fatalf("fetching bad url should result in non-nil error")
  195. }
  196. }
  197. func TestNoOCSPServers(t *testing.T) {
  198. badIssuer := goodCert
  199. badIssuer.IssuingCertificateURL = []string{" "}
  200. certIsRevokedOCSP(badIssuer, true)
  201. noOCSPCert := goodCert
  202. noOCSPCert.OCSPServer = make([]string, 0)
  203. if revoked, ok, _ := certIsRevokedOCSP(noOCSPCert, true); revoked || !ok {
  204. t.Fatalf("OCSP falsely registered as enabled for this certificate")
  205. }
  206. }