ACMEv2 client library for Go.

ocsp.go 1.6KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. package acmeapi
  2. import (
  3. "context"
  4. "crypto/x509"
  5. "encoding/base64"
  6. "fmt"
  7. denet "git.devever.net/hlandau/goutils/net"
  8. "golang.org/x/crypto/ocsp"
  9. "io/ioutil"
  10. "net/http"
  11. )
  12. // Checks OCSP for a certificate. The immediate issuer must be specified. If
  13. // the certificate does not support OCSP, (nil, nil) is returned. Uses HTTP
  14. // GET rather than POST. The response is verified. The caller must check the
  15. // response status. The raw OCSP response is also returned, even if parsing
  16. // failed and err is non-nil.
  17. //
  18. // This method is realm-independent.
  19. func (c *RealmClient) CheckOCSP(ctx context.Context, crt, issuer *x509.Certificate) (parsedResponse *ocsp.Response, rawResponse []byte, err error) {
  20. if len(crt.OCSPServer) == 0 {
  21. return
  22. }
  23. b, err := ocsp.CreateRequest(crt, issuer, nil)
  24. if err != nil {
  25. return
  26. }
  27. b64 := base64.StdEncoding.EncodeToString(b)
  28. path := crt.OCSPServer[0] + "/" + b64
  29. req, err := http.NewRequest("GET", path, nil)
  30. if err != nil {
  31. return
  32. }
  33. req.Header.Set("Accept", "application/ocsp-response")
  34. res, err := c.doReqActual(ctx, req)
  35. if err != nil {
  36. return
  37. }
  38. defer res.Body.Close()
  39. if res.StatusCode != 200 {
  40. err = fmt.Errorf("OCSP response has status %#v", res.Status)
  41. return
  42. }
  43. if res.Header.Get("Content-Type") != "application/ocsp-response" {
  44. err = fmt.Errorf("response to OCSP request had unexpected content type")
  45. return
  46. }
  47. // Read response, limiting response to 1MiB.
  48. rawResponse, err = ioutil.ReadAll(denet.LimitReader(res.Body, 1*1024*1024))
  49. if err != nil {
  50. return
  51. }
  52. parsedResponse, err = ocsp.ParseResponse(rawResponse, issuer)
  53. return
  54. }