ocsp.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package ocsp
  2. import (
  3. "bytes"
  4. "crypto/x509"
  5. "encoding/pem"
  6. "io"
  7. "net/http"
  8. "os"
  9. "github.com/xtls/xray-core/common/platform/filesystem"
  10. "golang.org/x/crypto/ocsp"
  11. )
  12. func GetOCSPForFile(path string) ([]byte, error) {
  13. return filesystem.ReadFile(path)
  14. }
  15. func CheckOCSPFileIsNotExist(path string) bool {
  16. _, err := os.Stat(path)
  17. if err != nil {
  18. return os.IsNotExist(err)
  19. }
  20. return false
  21. }
  22. func GetOCSPStapling(cert [][]byte, path string) ([]byte, error) {
  23. ocspData, err := GetOCSPForFile(path)
  24. if err != nil {
  25. ocspData, err = GetOCSPForCert(cert)
  26. if !CheckOCSPFileIsNotExist(path) {
  27. err = os.Remove(path)
  28. if err != nil {
  29. return nil, err
  30. }
  31. }
  32. newFile, err := os.Create(path)
  33. if err != nil {
  34. return nil, err
  35. }
  36. newFile.Write(ocspData)
  37. defer newFile.Close()
  38. }
  39. return ocspData, nil
  40. }
  41. func GetOCSPForCert(cert [][]byte) ([]byte, error) {
  42. bundle := new(bytes.Buffer)
  43. for _, derBytes := range cert {
  44. err := pem.Encode(bundle, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
  45. if err != nil {
  46. return nil, err
  47. }
  48. }
  49. pemBundle := bundle.Bytes()
  50. certificates, err := parsePEMBundle(pemBundle)
  51. if err != nil {
  52. return nil, err
  53. }
  54. issuedCert := certificates[0]
  55. if len(issuedCert.OCSPServer) == 0 {
  56. return nil, newError("no OCSP server specified in cert")
  57. }
  58. if len(certificates) == 1 {
  59. if len(issuedCert.IssuingCertificateURL) == 0 {
  60. return nil, newError("no issuing certificate URL")
  61. }
  62. resp, errC := http.Get(issuedCert.IssuingCertificateURL[0])
  63. if errC != nil {
  64. return nil, newError("no issuing certificate URL")
  65. }
  66. defer resp.Body.Close()
  67. issuerBytes, errC := io.ReadAll(resp.Body)
  68. if errC != nil {
  69. return nil, newError(errC)
  70. }
  71. issuerCert, errC := x509.ParseCertificate(issuerBytes)
  72. if errC != nil {
  73. return nil, newError(errC)
  74. }
  75. certificates = append(certificates, issuerCert)
  76. }
  77. issuerCert := certificates[1]
  78. ocspReq, err := ocsp.CreateRequest(issuedCert, issuerCert, nil)
  79. if err != nil {
  80. return nil, err
  81. }
  82. reader := bytes.NewReader(ocspReq)
  83. req, err := http.Post(issuedCert.OCSPServer[0], "application/ocsp-request", reader)
  84. if err != nil {
  85. return nil, newError(err)
  86. }
  87. defer req.Body.Close()
  88. ocspResBytes, err := io.ReadAll(req.Body)
  89. if err != nil {
  90. return nil, newError(err)
  91. }
  92. return ocspResBytes, nil
  93. }
  94. // parsePEMBundle parses a certificate bundle from top to bottom and returns
  95. // a slice of x509 certificates. This function will error if no certificates are found.
  96. func parsePEMBundle(bundle []byte) ([]*x509.Certificate, error) {
  97. var certificates []*x509.Certificate
  98. var certDERBlock *pem.Block
  99. for {
  100. certDERBlock, bundle = pem.Decode(bundle)
  101. if certDERBlock == nil {
  102. break
  103. }
  104. if certDERBlock.Type == "CERTIFICATE" {
  105. cert, err := x509.ParseCertificate(certDERBlock.Bytes)
  106. if err != nil {
  107. return nil, err
  108. }
  109. certificates = append(certificates, cert)
  110. }
  111. }
  112. if len(certificates) == 0 {
  113. return nil, newError("no certificates were found while parsing the bundle")
  114. }
  115. return certificates, nil
  116. }