get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/certidp/ocsp_responder.go (about) 1 // Copyright 2023 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package certidp 15 16 import ( 17 "encoding/base64" 18 "fmt" 19 "io" 20 "net/http" 21 "strings" 22 "time" 23 24 "golang.org/x/crypto/ocsp" 25 ) 26 27 func FetchOCSPResponse(link *ChainLink, opts *OCSPPeerConfig, log *Log) ([]byte, error) { 28 if link == nil || link.Leaf == nil || link.Issuer == nil || opts == nil || log == nil { 29 return nil, fmt.Errorf(ErrInvalidChainlink) 30 } 31 32 timeout := time.Duration(opts.Timeout * float64(time.Second)) 33 if timeout <= 0*time.Second { 34 timeout = DefaultOCSPResponderTimeout 35 } 36 37 getRequestBytes := func(u string, hc *http.Client) ([]byte, error) { 38 resp, err := hc.Get(u) 39 if err != nil { 40 return nil, err 41 } 42 defer resp.Body.Close() 43 if resp.StatusCode != http.StatusOK { 44 return nil, fmt.Errorf(ErrBadResponderHTTPStatus, resp.StatusCode) 45 } 46 return io.ReadAll(resp.Body) 47 } 48 49 // Request documentation: 50 // https://tools.ietf.org/html/rfc6960#appendix-A.1 51 52 reqDER, err := ocsp.CreateRequest(link.Leaf, link.Issuer, nil) 53 if err != nil { 54 return nil, err 55 } 56 57 reqEnc := base64.StdEncoding.EncodeToString(reqDER) 58 59 responders := *link.OCSPWebEndpoints 60 61 if len(responders) == 0 { 62 return nil, fmt.Errorf(ErrNoAvailOCSPServers) 63 } 64 65 var raw []byte 66 hc := &http.Client{ 67 Timeout: timeout, 68 } 69 for _, u := range responders { 70 url := u.String() 71 log.Debugf(DbgMakingCARequest, url) 72 url = strings.TrimSuffix(url, "/") 73 raw, err = getRequestBytes(fmt.Sprintf("%s/%s", url, reqEnc), hc) 74 if err == nil { 75 break 76 } 77 } 78 if err != nil { 79 return nil, fmt.Errorf(ErrFailedWithAllRequests, err) 80 } 81 82 return raw, nil 83 }