123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- package ocsp
- import (
- "bytes"
- "encoding/base64"
- "encoding/json"
- "io"
- "net/http"
- "net/http/httptest"
- "os"
- "testing"
- "time"
- "github.com/cloudflare/cfssl/api"
- "github.com/cloudflare/cfssl/helpers"
- "github.com/cloudflare/cfssl/ocsp"
- goocsp "golang.org/x/crypto/ocsp"
- )
- const (
- testCaFile = "../../ocsp/testdata/ca.pem"
- testRespCertFile = "../../ocsp/testdata/server.crt"
- testKeyFile = "../../ocsp/testdata/server.key"
- testCertFile = "../../ocsp/testdata/cert.pem"
- )
- func newTestHandler(t *testing.T) http.Handler {
- // arbitrary duration
- dur, _ := time.ParseDuration("1ms")
- s, err := ocsp.NewSignerFromFile(testCaFile, testRespCertFile, testKeyFile, dur)
- if err != nil {
- t.Fatalf("Signer creation failed %v", err)
- }
- return NewHandler(s)
- }
- func TestNewHandler(t *testing.T) {
- newTestHandler(t)
- }
- func newSignServer(t *testing.T) *httptest.Server {
- ts := httptest.NewServer(newTestHandler(t))
- return ts
- }
- func testSignFile(t *testing.T, certFile, status string, reason int, revokedAt string, hash string) (resp *http.Response, body []byte) {
- ts := newSignServer(t)
- defer ts.Close()
- obj := map[string]interface{}{}
- if certFile != "" {
- c, err := os.ReadFile(certFile)
- if err != nil {
- t.Fatal(err)
- }
- obj["certificate"] = string(c)
- }
- if status != "" {
- obj["status"] = status
- }
- obj["reason"] = reason
- if revokedAt != "" {
- obj["revoked_at"] = revokedAt
- }
- obj["issuer_hash"] = hash
- blob, err := json.Marshal(obj)
- if err != nil {
- t.Fatal(err)
- }
- resp, err = http.Post(ts.URL, "application/json", bytes.NewReader(blob))
- if err != nil {
- t.Fatal(err)
- }
- body, err = io.ReadAll(resp.Body)
- if err != nil {
- t.Fatal(err)
- }
- return
- }
- type signTest struct {
- CertificateFile string
- Status string
- Reason int
- RevokedAt string
- ExpectedHTTPStatus int
- ExpectedSuccess bool
- ExpectedErrorCode int
- IssuerHash string
- }
- var signTests = []signTest{
- {
- CertificateFile: testCertFile,
- ExpectedHTTPStatus: http.StatusOK,
- ExpectedSuccess: true,
- ExpectedErrorCode: 0,
- },
- {
- CertificateFile: testCertFile,
- Status: "revoked",
- Reason: 1,
- ExpectedHTTPStatus: http.StatusOK,
- ExpectedSuccess: true,
- ExpectedErrorCode: 0,
- },
- {
- CertificateFile: testCertFile,
- Status: "revoked",
- RevokedAt: "now",
- ExpectedHTTPStatus: http.StatusOK,
- ExpectedSuccess: true,
- ExpectedErrorCode: 0,
- },
- {
- CertificateFile: testCertFile,
- Status: "revoked",
- RevokedAt: "2015-08-15",
- ExpectedHTTPStatus: http.StatusOK,
- ExpectedSuccess: true,
- ExpectedErrorCode: 0,
- },
- {
- CertificateFile: testCertFile,
- Status: "revoked",
- RevokedAt: "a",
- ExpectedHTTPStatus: http.StatusBadRequest,
- ExpectedSuccess: false,
- ExpectedErrorCode: http.StatusBadRequest,
- },
- {
- CertificateFile: "",
- Status: "",
- ExpectedHTTPStatus: http.StatusBadRequest,
- ExpectedSuccess: false,
- ExpectedErrorCode: http.StatusBadRequest,
- },
- {
- CertificateFile: testCertFile,
- Status: "_",
- ExpectedHTTPStatus: http.StatusBadRequest,
- ExpectedSuccess: false,
- ExpectedErrorCode: 8200,
- },
- {
- CertificateFile: testCertFile,
- IssuerHash: "SHA256",
- ExpectedHTTPStatus: http.StatusOK,
- ExpectedSuccess: true,
- ExpectedErrorCode: 0,
- },
- {
- CertificateFile: testCertFile,
- IssuerHash: "MD4",
- ExpectedHTTPStatus: http.StatusBadRequest,
- ExpectedSuccess: false,
- ExpectedErrorCode: http.StatusBadRequest,
- },
- }
- func TestSign(t *testing.T) {
- for i, test := range signTests {
- resp, body := testSignFile(t, test.CertificateFile, test.Status, test.Reason, test.RevokedAt, test.IssuerHash)
- if resp.StatusCode != test.ExpectedHTTPStatus {
- t.Logf("Test %d: expected: %d, have %d", i, test.ExpectedHTTPStatus, resp.StatusCode)
- t.Fatal(resp.Status, test.ExpectedHTTPStatus, string(body))
- }
- message := new(api.Response)
- err := json.Unmarshal(body, message)
- if err != nil {
- t.Logf("failed to read response body: %v", err)
- t.Fatal(resp.Status, test.ExpectedHTTPStatus, message)
- }
- if test.ExpectedSuccess != message.Success {
- t.Logf("Test %d: expected: %v, have %v", i, test.ExpectedSuccess, message.Success)
- t.Fatal(resp.Status, test.ExpectedHTTPStatus, message)
- }
- if !test.ExpectedSuccess {
- if test.ExpectedErrorCode != message.Errors[0].Code {
- t.Fatalf("Test %d: expected: %v, have %v", i, test.ExpectedErrorCode, message.Errors[0].Code)
- t.Fatal(resp.Status, test.ExpectedHTTPStatus, message)
- }
- continue
- }
- result, ok := message.Result.(map[string]interface{})
- if !ok {
- t.Logf("failed to read result")
- t.Fatal(resp.Status, test.ExpectedHTTPStatus, string(body))
- }
- b64Resp, ok := result["ocspResponse"].(string)
- if !ok {
- t.Logf("failed to find ocspResponse")
- t.Fatal(resp.Status, test.ExpectedHTTPStatus, string(body))
- }
- der, err := base64.StdEncoding.DecodeString(b64Resp)
- if err != nil {
- t.Logf("failed to decode base64")
- t.Fatal(resp.Status, test.ExpectedHTTPStatus, b64Resp)
- }
- ocspResp, err := goocsp.ParseResponse(der, nil)
- if err != nil {
- t.Logf("failed to parse ocsp response: %v", err)
- t.Fatal(resp.Status, test.ExpectedHTTPStatus, b64Resp)
- }
- // should default to good
- if test.Status == "" {
- test.Status = "good"
- }
- intStatus := ocsp.StatusCode[test.Status]
- if ocspResp.Status != intStatus {
- t.Fatalf("Test %d incorrect status: expected: %v, have %v", i, intStatus, ocspResp.Status)
- t.Fatal(ocspResp.Status, intStatus, ocspResp)
- }
- if test.Status == "revoked" {
- if ocspResp.RevocationReason != test.Reason {
- t.Fatalf("Test %d incorrect reason: expected: %v, have %v", i, test.Reason, ocspResp.RevocationReason)
- t.Fatal(ocspResp.RevocationReason, test.Reason, ocspResp)
- }
- var r time.Time
- if test.RevokedAt == "" || test.RevokedAt == "now" {
- r = time.Now().UTC().Truncate(helpers.OneDay)
- } else {
- r, _ = time.Parse("2006-01-02", test.RevokedAt)
- }
- if !ocspResp.RevokedAt.Truncate(helpers.OneDay).Equal(r) {
- t.Fatalf("Test %d incorrect revokedAt: expected: %v, have %v", i, r, ocspResp.RevokedAt)
- t.Fatal(ocspResp.RevokedAt, test.RevokedAt, ocspResp)
- }
- }
- }
- }
|