11package certificate
22
33import (
4+ "bytes"
5+ "crypto"
46 "crypto/sha256"
57 "crypto/x509"
68 "fmt"
9+ "io"
710 "math/big"
11+ "net/http"
12+ "net/url"
13+ "strings"
814 "time"
915
1016 etls "github.com/elmasy-com/elmasy/pkg/protocols/tls"
17+ "golang.org/x/crypto/ocsp"
1118)
1219
1320type PubKey struct {
@@ -60,6 +67,58 @@ func Grab(network, ip, port string, timeout time.Duration, servername string) ([
6067 return nil , fmt .Errorf ("TLS not supported" )
6168}
6269
70+ func verifyOCSP (leaf x509.Certificate , issuer x509.Certificate ) error {
71+
72+ opts := ocsp.RequestOptions {Hash : crypto .SHA1 }
73+
74+ buf , err := ocsp .CreateRequest (& leaf , & issuer , & opts )
75+ if err != nil {
76+ return err
77+ }
78+
79+ req , err := http .NewRequest (http .MethodPost , leaf .OCSPServer [0 ], bytes .NewBuffer (buf ))
80+ if err != nil {
81+ return err
82+ }
83+
84+ url , err := url .Parse (leaf .OCSPServer [0 ])
85+ if err != nil {
86+ return err
87+ }
88+ req .Header .Add ("Content-Type" , "application/ocsp-request" )
89+ req .Header .Add ("Accept" , "application/ocsp-response" )
90+ req .Header .Add ("host" , url .Host )
91+
92+ client := http.Client {Timeout : 5 * time .Second }
93+
94+ resp , err := client .Do (req )
95+ if err != nil {
96+ return err
97+ }
98+ defer resp .Body .Close ()
99+
100+ body , err := io .ReadAll (resp .Body )
101+ if err != nil {
102+ return err
103+ }
104+
105+ ocspResp , err := ocsp .ParseResponseForCert (body , & leaf , & issuer )
106+ if err != nil {
107+ return err
108+ }
109+
110+ switch ocspResp .Status {
111+ case ocsp .Good :
112+ return nil
113+ case ocsp .Revoked :
114+ return fmt .Errorf ("revoked" )
115+ case ocsp .Unknown :
116+ return fmt .Errorf ("unknown" )
117+ default :
118+ return fmt .Errorf ("invalid status: %d" , ocspResp .Status )
119+ }
120+ }
121+
63122func Verify (certs []x509.Certificate , servername string ) error {
64123
65124 if len (certs ) < 1 {
@@ -77,9 +136,20 @@ func Verify(certs []x509.Certificate, servername string) error {
77136 opts .Intermediates = pool
78137 }
79138
80- _ , err := certs [0 ].Verify (opts )
139+ if _ , err := certs [0 ].Verify (opts ); err != nil {
140+ // remove the "x509: " prefix
141+ e := strings .TrimPrefix (err .Error (), "x509: " )
142+ return fmt .Errorf ("%s" , e )
143+ }
144+
145+ if len (certs [0 ].OCSPServer ) > 0 && len (certs ) >= 2 {
146+
147+ if err := verifyOCSP (certs [0 ], certs [1 ]); err != nil {
148+ return err
149+ }
150+ }
81151
82- return err
152+ return nil
83153}
84154
85155// parseLeafCert parse the leaf cert and fill the fields of r (result Cert)
0 commit comments