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