getOCSPForCert takes a PEM encoded cert or cert bundle returning the raw OCSP response, the parsed response, and an error, if any. The returned []byte can be passed directly into the OCSPStaple property of a tls.Certificate. If the bundle only contains the issued certificate, this function will try
(ocspConfig OCSPConfig, bundle []byte)
| 145 | // |
| 146 | // Borrowed from xenolf. |
| 147 | func getOCSPForCert(ocspConfig OCSPConfig, bundle []byte) ([]byte, *ocsp.Response, error) { |
| 148 | // TODO: Perhaps this should be synchronized too, with a Locker? |
| 149 | |
| 150 | certificates, err := parseCertsFromPEMBundle(bundle) |
| 151 | if err != nil { |
| 152 | return nil, nil, err |
| 153 | } |
| 154 | |
| 155 | // We expect the certificate slice to be ordered downwards the chain. |
| 156 | // SRV CRT -> CA. We need to pull the leaf and issuer certs out of it, |
| 157 | // which should always be the first two certificates. If there's no |
| 158 | // OCSP server listed in the leaf cert, there's nothing to do. And if |
| 159 | // we have only one certificate so far, we need to get the issuer cert. |
| 160 | issuedCert := certificates[0] |
| 161 | if len(issuedCert.OCSPServer) == 0 { |
| 162 | return nil, nil, ErrNoOCSPServerSpecified |
| 163 | } |
| 164 | |
| 165 | // apply override for responder URL |
| 166 | respURL := issuedCert.OCSPServer[0] |
| 167 | if len(ocspConfig.ResponderOverrides) > 0 { |
| 168 | if override, ok := ocspConfig.ResponderOverrides[respURL]; ok { |
| 169 | respURL = override |
| 170 | } |
| 171 | } |
| 172 | if respURL == "" { |
| 173 | return nil, nil, fmt.Errorf("override disables querying OCSP responder: %v", issuedCert.OCSPServer[0]) |
| 174 | } |
| 175 | |
| 176 | // configure HTTP client if necessary |
| 177 | httpClient := http.DefaultClient |
| 178 | if ocspConfig.HTTPProxy != nil { |
| 179 | httpClient = &http.Client{ |
| 180 | Transport: &http.Transport{ |
| 181 | Proxy: ocspConfig.HTTPProxy, |
| 182 | }, |
| 183 | Timeout: 30 * time.Second, |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | // get issuer certificate if needed |
| 188 | if len(certificates) == 1 { |
| 189 | if len(issuedCert.IssuingCertificateURL) == 0 { |
| 190 | return nil, nil, fmt.Errorf("no URL to issuing certificate") |
| 191 | } |
| 192 | |
| 193 | resp, err := httpClient.Get(issuedCert.IssuingCertificateURL[0]) |
| 194 | if err != nil { |
| 195 | return nil, nil, fmt.Errorf("getting issuer certificate: %v", err) |
| 196 | } |
| 197 | defer resp.Body.Close() |
| 198 | |
| 199 | issuerBytes, err := io.ReadAll(io.LimitReader(resp.Body, 1024*1024)) |
| 200 | if err != nil { |
| 201 | return nil, nil, fmt.Errorf("reading issuer certificate: %v", err) |
| 202 | } |
| 203 | |
| 204 | issuerCert, err := x509.ParseCertificate(issuerBytes) |
no test coverage detected
searching dependent graphs…