// Certificate is used by clients to request a copy of their current certificate, or to // request a reissuance of the certificate. func (wfe *WebFrontEndImpl) Certificate(ctx context.Context, logEvent *requestEvent, response http.ResponseWriter, request *http.Request) { serial := request.URL.Path // Certificate paths consist of the CertBase path, plus exactly sixteen hex // digits. if !core.ValidSerial(serial) { logEvent.AddError("certificate serial provided was not valid: %s", serial) wfe.sendError(response, logEvent, probs.NotFound("Certificate not found"), nil) return } logEvent.Extra["RequestedSerial"] = serial cert, err := wfe.SA.GetCertificate(ctx, serial) // TODO(#991): handle db errors if err != nil { logEvent.AddError("unable to get certificate by serial id %#v: %s", serial, err) if strings.HasPrefix(err.Error(), "gorp: multiple rows returned") { wfe.sendError(response, logEvent, probs.Conflict("Multiple certificates with same short serial"), err) } else { wfe.sendError(response, logEvent, probs.NotFound("Certificate not found"), err) } return } // TODO Content negotiation response.Header().Set("Content-Type", "application/pkix-cert") response.Header().Add("Link", link(issuerPath, "up")) response.WriteHeader(http.StatusOK) if _, err = response.Write(cert.DER); err != nil { logEvent.AddError(err.Error()) wfe.log.Warning(fmt.Sprintf("Could not write response: %s", err)) } return }
// Certificate is used by clients to request a copy of their current certificate, or to // request a reissuance of the certificate. func (wfe *WebFrontEndImpl) Certificate(ctx context.Context, logEvent *requestEvent, response http.ResponseWriter, request *http.Request) { path := request.URL.Path // Certificate paths consist of the CertBase path, plus exactly sixteen hex // digits. if !strings.HasPrefix(path, CertPath) { logEvent.AddError("this request path should not have gotten to Certificate: %#v is not a prefix of %#v", path, CertPath) wfe.sendError(response, logEvent, probs.NotFound("Certificate not found"), nil) addNoCacheHeader(response) return } serial := path[len(CertPath):] if !core.ValidSerial(serial) { logEvent.AddError("certificate serial provided was not valid: %s", serial) wfe.sendError(response, logEvent, probs.NotFound("Certificate not found"), nil) addNoCacheHeader(response) return } logEvent.Extra["RequestedSerial"] = serial cert, err := wfe.SA.GetCertificate(ctx, serial) // TODO(#991): handle db errors if err != nil { logEvent.AddError("unable to get certificate by serial id %#v: %s", serial, err) if strings.HasPrefix(err.Error(), "gorp: multiple rows returned") { wfe.sendError(response, logEvent, probs.Conflict("Multiple certificates with same short serial"), err) } else { addNoCacheHeader(response) wfe.sendError(response, logEvent, probs.NotFound("Certificate not found"), err) } return } parsedCertificate, err := x509.ParseCertificate([]byte(cert.DER)) if err != nil { logEvent.AddError("unable to parse certificate: %s", err) wfe.sendError(response, logEvent, probs.Malformed("Unable to parse certificate"), err) return } if err = wfe.addIssuerCertificateURLs(response, parsedCertificate); err != nil { logEvent.AddError("unable to parse IssuingCertificateURL: %s", err) wfe.sendError(response, logEvent, probs.Malformed("unable to parse IssuingCertificateURL"), err) return } addCacheHeader(response, wfe.CertCacheDuration.Seconds()) // TODO Content negotiation response.Header().Set("Content-Type", "application/pkix-cert") response.WriteHeader(http.StatusOK) if _, err = response.Write(cert.DER); err != nil { logEvent.AddError(err.Error()) wfe.log.Warning(fmt.Sprintf("Could not write response: %s", err)) } return }
// GetCertificateStatus takes a hexadecimal string representing the full 128-bit serial // number of a certificate and returns data about that certificate's current // validity. func (ssa *SQLStorageAuthority) GetCertificateStatus(ctx context.Context, serial string) (core.CertificateStatus, error) { if !core.ValidSerial(serial) { err := fmt.Errorf("Invalid certificate serial %s", serial) return core.CertificateStatus{}, err } var status core.CertificateStatus if features.Enabled(features.CertStatusOptimizationsMigrated) { statusObj, err := ssa.dbMap.Get(certStatusModelv2{}, serial) if err != nil { return status, err } if statusObj == nil { return status, nil } statusModel := statusObj.(*certStatusModelv2) status = core.CertificateStatus{ Serial: statusModel.Serial, SubscriberApproved: statusModel.SubscriberApproved, Status: statusModel.Status, OCSPLastUpdated: statusModel.OCSPLastUpdated, RevokedDate: statusModel.RevokedDate, RevokedReason: statusModel.RevokedReason, LastExpirationNagSent: statusModel.LastExpirationNagSent, OCSPResponse: statusModel.OCSPResponse, NotAfter: statusModel.NotAfter, IsExpired: statusModel.IsExpired, LockCol: statusModel.LockCol, } } else { statusObj, err := ssa.dbMap.Get(certStatusModelv1{}, serial) if err != nil { return status, err } if statusObj == nil { return status, nil } statusModel := statusObj.(*certStatusModelv1) status = core.CertificateStatus{ Serial: statusModel.Serial, SubscriberApproved: statusModel.SubscriberApproved, Status: statusModel.Status, OCSPLastUpdated: statusModel.OCSPLastUpdated, RevokedDate: statusModel.RevokedDate, RevokedReason: statusModel.RevokedReason, LastExpirationNagSent: statusModel.LastExpirationNagSent, OCSPResponse: statusModel.OCSPResponse, LockCol: statusModel.LockCol, } } return status, nil }
// GetCertificateStatus takes a hexadecimal string representing the full 128-bit serial // number of a certificate and returns data about that certificate's current // validity. func (ssa *SQLStorageAuthority) GetCertificateStatus(serial string) (status core.CertificateStatus, err error) { if !core.ValidSerial(serial) { err := fmt.Errorf("Invalid certificate serial %s", serial) return core.CertificateStatus{}, err } certificateStats, err := ssa.dbMap.Get(core.CertificateStatus{}, serial) if err != nil { return } status = *certificateStats.(*core.CertificateStatus) return }
// GetCertificate takes a serial number and returns the corresponding // certificate, or error if it does not exist. func (ssa *SQLStorageAuthority) GetCertificate(ctx context.Context, serial string) (core.Certificate, error) { if !core.ValidSerial(serial) { err := fmt.Errorf("Invalid certificate serial %s", serial) return core.Certificate{}, err } cert, err := SelectCertificate(ssa.dbMap, "WHERE serial = ?", serial) if err == sql.ErrNoRows { return core.Certificate{}, core.NotFoundError(fmt.Sprintf("No certificate found for %s", serial)) } if err != nil { return core.Certificate{}, err } return cert, err }
// Certificate is used by clients to request a copy of their current certificate, or to // request a reissuance of the certificate. func (wfe *WebFrontEndImpl) Certificate(response http.ResponseWriter, request *http.Request) { logEvent := wfe.populateRequestEvent(request) defer wfe.logRequestDetails(&logEvent) path := request.URL.Path // Certificate paths consist of the CertBase path, plus exactly sixteen hex // digits. if !strings.HasPrefix(path, CertPath) { logEvent.Error = "Certificate not found" wfe.sendError(response, logEvent.Error, path, http.StatusNotFound) addNoCacheHeader(response) return } serial := path[len(CertPath):] if !core.ValidSerial(serial) { logEvent.Error = "Certificate not found" wfe.sendError(response, logEvent.Error, serial, http.StatusNotFound) addNoCacheHeader(response) return } wfe.log.Debug(fmt.Sprintf("Requested certificate ID %s", serial)) logEvent.Extra["RequestedSerial"] = serial cert, err := wfe.SA.GetCertificate(serial) if err != nil { logEvent.Error = err.Error() if strings.HasPrefix(err.Error(), "gorp: multiple rows returned") { wfe.sendError(response, "Multiple certificates with same short serial", err, http.StatusConflict) } else { addNoCacheHeader(response) wfe.sendError(response, "Certificate not found", err, http.StatusNotFound) } return } addCacheHeader(response, wfe.CertCacheDuration.Seconds()) // TODO Content negotiation response.Header().Set("Content-Type", "application/pkix-cert") response.Header().Add("Link", link(IssuerPath, "up")) response.WriteHeader(http.StatusOK) if _, err = response.Write(cert.DER); err != nil { logEvent.Error = err.Error() wfe.log.Warning(fmt.Sprintf("Could not write response: %s", err)) } return }
// Certificate is used by clients to request a copy of their current certificate, or to // request a reissuance of the certificate. func (wfe *WebFrontEndImpl) Certificate(logEvent *requestEvent, response http.ResponseWriter, request *http.Request) { path := request.URL.Path // Certificate paths consist of the CertBase path, plus exactly sixteen hex // digits. if !strings.HasPrefix(path, CertPath) { logEvent.AddError("this request path should not have gotten to Certificate: %#v is not a prefix of %#v", path, CertPath) wfe.sendError(response, logEvent, "Certificate not found", path, http.StatusNotFound) addNoCacheHeader(response) return } serial := path[len(CertPath):] if !core.ValidSerial(serial) { logEvent.AddError("certificate serial provided was not valid: %s", serial) wfe.sendError(response, logEvent, "Certificate not found", serial, http.StatusNotFound) addNoCacheHeader(response) return } logEvent.Extra["RequestedSerial"] = serial cert, err := wfe.SA.GetCertificate(serial) if err != nil { logEvent.AddError("unable to get certificate by serial id %#v: %s", serial, err) if strings.HasPrefix(err.Error(), "gorp: multiple rows returned") { wfe.sendError(response, logEvent, "Multiple certificates with same short serial", err, http.StatusConflict) } else { addNoCacheHeader(response) wfe.sendError(response, logEvent, "Certificate not found", err, http.StatusNotFound) } return } addCacheHeader(response, wfe.CertCacheDuration.Seconds()) // TODO Content negotiation response.Header().Set("Content-Type", "application/pkix-cert") response.Header().Add("Link", link(IssuerPath, "up")) response.WriteHeader(http.StatusOK) if _, err = response.Write(cert.DER); err != nil { logEvent.AddError(err.Error()) wfe.log.Warning(fmt.Sprintf("Could not write response: %s", err)) } return }
// GetCertificate takes a serial number and returns the corresponding // certificate, or error if it does not exist. func (ssa *SQLStorageAuthority) GetCertificate(serial string) (core.Certificate, error) { if !core.ValidSerial(serial) { err := fmt.Errorf("Invalid certificate serial %s", serial) return core.Certificate{}, err } certObj, err := ssa.dbMap.Get(core.Certificate{}, serial) if err != nil { return core.Certificate{}, err } if certObj == nil { ssa.log.Debug(fmt.Sprintf("Nil cert for %s", serial)) return core.Certificate{}, fmt.Errorf("Certificate does not exist for %s", serial) } certPtr, ok := certObj.(*core.Certificate) if !ok { ssa.log.Debug("Failed to convert cert") return core.Certificate{}, fmt.Errorf("Error converting certificate response for %s", serial) } return *certPtr, err }