Convert the probs functions to be formatters. (#3708)

Many of the probs.XYZ calls are of the form probs.XYZ(fmt.Sprintf(...)).
Convert these functions to take a format string and optional arguments,
following the same pattern used in the errors package. Convert the
various call sites to remove the now redundant fmt.Sprintf calls.
This commit is contained in:
Joel Sing 2018-05-12 04:51:16 +10:00 committed by Roland Bracewell Shoemaker
parent 087074c73b
commit 9990d14654
7 changed files with 98 additions and 122 deletions

View File

@ -79,73 +79,70 @@ func ProblemDetailsToStatusCode(prob *ProblemDetails) int {
// BadNonce returns a ProblemDetails with a BadNonceProblem and a 400 Bad
// Request status code.
func BadNonce(detail string) *ProblemDetails {
func BadNonce(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: BadNonceProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusBadRequest,
}
}
// RejectedIdentifier returns a ProblemDetails with a RejectedIdentifierProblem and a 400 Bad
// Request status code.
func RejectedIdentifier(detail string) *ProblemDetails {
func RejectedIdentifier(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: RejectedIdentifierProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusBadRequest,
}
}
// Conflict returns a ProblemDetails with a MalformedProblem and a 409 Conflict
// status code.
func Conflict(detail string) *ProblemDetails {
func Conflict(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: MalformedProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusConflict,
}
}
// Malformed returns a ProblemDetails with a MalformedProblem and a 400 Bad
// Request status code.
func Malformed(detail string, args ...interface{}) *ProblemDetails {
if len(args) > 0 {
detail = fmt.Sprintf(detail, args...)
}
func Malformed(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: MalformedProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusBadRequest,
}
}
// NotFound returns a ProblemDetails with a MalformedProblem and a 404 Not Found
// status code.
func NotFound(detail string) *ProblemDetails {
func NotFound(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: MalformedProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusNotFound,
}
}
// ServerInternal returns a ProblemDetails with a ServerInternalProblem and a
// 500 Internal Server Failure status code.
func ServerInternal(detail string) *ProblemDetails {
func ServerInternal(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: ServerInternalProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusInternalServerError,
}
}
// Unauthorized returns a ProblemDetails with an UnauthorizedProblem and a 403
// Forbidden status code.
func Unauthorized(detail string) *ProblemDetails {
func Unauthorized(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: UnauthorizedProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusForbidden,
}
}
@ -172,85 +169,85 @@ func ContentLengthRequired() *ProblemDetails {
// InvalidContentType returns a ProblemDetails suitable for a missing
// ContentType header, or an incorrect ContentType header
func InvalidContentType(detail string) *ProblemDetails {
func InvalidContentType(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: MalformedProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusUnsupportedMediaType,
}
}
// InvalidEmail returns a ProblemDetails representing an invalid email address
// error
func InvalidEmail(detail string) *ProblemDetails {
func InvalidEmail(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: InvalidEmailProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusBadRequest,
}
}
// ConnectionFailure returns a ProblemDetails representing a ConnectionProblem
// error
func ConnectionFailure(detail string) *ProblemDetails {
func ConnectionFailure(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: ConnectionProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusBadRequest,
}
}
// UnknownHost returns a ProblemDetails representing an UnknownHostProblem error
func UnknownHost(detail string) *ProblemDetails {
func UnknownHost(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: UnknownHostProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusBadRequest,
}
}
// RateLimited returns a ProblemDetails representing a RateLimitedProblem error
func RateLimited(detail string) *ProblemDetails {
func RateLimited(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: RateLimitedProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: statusTooManyRequests,
}
}
// TLSError returns a ProblemDetails representing a TLSProblem error
func TLSError(detail string) *ProblemDetails {
func TLSError(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: TLSProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusBadRequest,
}
}
// AccountDoesNotExist returns a ProblemDetails representing an
// AccountDoesNotExistProblem error
func AccountDoesNotExist(detail string) *ProblemDetails {
func AccountDoesNotExist(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: AccountDoesNotExistProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusBadRequest,
}
}
// CAA returns a ProblemDetails representing a CAAProblem
func CAA(detail string) *ProblemDetails {
func CAA(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: CAAProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusForbidden,
}
}
// DNS returns a ProblemDetails representing a DNSProblem
func DNS(detail string) *ProblemDetails {
func DNS(detail string, a ...interface{}) *ProblemDetails {
return &ProblemDetails{
Type: DNSProblem,
Detail: detail,
Detail: fmt.Sprintf(detail, a...),
HTTPStatus: http.StatusBadRequest,
}
}

View File

@ -42,12 +42,12 @@ func (va *ValidationAuthorityImpl) checkCAA(
identifier core.AcmeIdentifier) *probs.ProblemDetails {
present, valid, err := va.checkCAARecords(ctx, identifier)
if err != nil {
return probs.DNS(err.Error())
return probs.DNS("%v", err)
}
va.log.AuditInfof("Checked CAA records for %s, [Present: %t, Valid for issuance: %t]",
identifier.Value, present, valid)
if !valid {
return probs.CAA(fmt.Sprintf("CAA record for %s prevents issuance", identifier.Value))
return probs.CAA("CAA record for %s prevents issuance", identifier.Value)
}
return nil
}

View File

@ -171,15 +171,12 @@ type verificationRequestEvent struct {
func (va ValidationAuthorityImpl) getAddrs(ctx context.Context, hostname string) ([]net.IP, *probs.ProblemDetails) {
addrs, err := va.dnsClient.LookupHost(ctx, hostname)
if err != nil {
problem := probs.DNS(err.Error())
problem := probs.DNS("%v", err)
return nil, problem
}
if len(addrs) == 0 {
problem := probs.UnknownHost(
fmt.Sprintf("No valid IP addresses found for %s", hostname),
)
return nil, problem
return nil, probs.UnknownHost("No valid IP addresses found for %s", hostname)
}
va.log.Debugf("Resolved addresses for %s: %s", hostname, addrs)
return addrs, nil
@ -470,19 +467,19 @@ func (va *ValidationAuthorityImpl) fetchHTTP(ctx context.Context, identifier cor
err = closeErr
}
if err != nil {
va.log.Infof("Error reading HTTP response body from %s. err=[%#v] errStr=[%s]", url.String(), err, err)
return nil, validationRecords, probs.Unauthorized(fmt.Sprintf("Error reading HTTP response body: %v", err))
va.log.Infof("Error reading HTTP response body from %s. err=[%#v] errStr=[%s]", url, err, err)
return nil, validationRecords, probs.Unauthorized("Error reading HTTP response body: %v", err)
}
// io.LimitedReader will silently truncate a Reader so if the
// resulting payload is the same size as maxResponseSize fail
if len(body) >= maxResponseSize {
return nil, validationRecords, probs.Unauthorized(fmt.Sprintf("Invalid response from %s: \"%s\"", url.String(), body))
return nil, validationRecords, probs.Unauthorized("Invalid response from %s: \"%s\"", url, body)
}
if httpResponse.StatusCode != 200 {
va.log.Infof("Non-200 status code from HTTP: %s returned %d", url.String(), httpResponse.StatusCode)
return nil, validationRecords, probs.Unauthorized(fmt.Sprintf("Invalid response from %s [%s]: %d",
url.String(), validationRecords[len(validationRecords)-1].AddressUsed, httpResponse.StatusCode))
va.log.Infof("Non-200 status code from HTTP: %s returned %d", url, httpResponse.StatusCode)
return nil, validationRecords, probs.Unauthorized("Invalid response from %s [%s]: %d",
url, validationRecords[len(validationRecords)-1].AddressUsed, httpResponse.StatusCode)
}
return body, validationRecords, nil
@ -521,8 +518,7 @@ func (va *ValidationAuthorityImpl) tryGetTLSSNICerts(ctx context.Context, identi
// This shouldn't happen, but be defensive about it anyway
if len(addresses) < 1 {
return nil, validationRecords, probs.Malformed(
fmt.Sprintf("no IP addresses found for %q", identifier.Value))
return nil, validationRecords, probs.Malformed("no IP addresses found for %q", identifier.Value)
}
// If there is at least one IPv6 address then try it first
@ -545,14 +541,12 @@ func (va *ValidationAuthorityImpl) tryGetTLSSNICerts(ctx context.Context, identi
// If there are no IPv4 addresses and we tried an IPv6 address return
// an error - there's nothing left to try
if len(v4) == 0 && len(thisRecord.AddressesTried) > 0 {
return nil, validationRecords, probs.Malformed(
fmt.Sprintf("Unable to contact %q at %q, no IPv4 addresses to try as fallback",
thisRecord.Hostname, thisRecord.AddressesTried[0]))
return nil, validationRecords, probs.Malformed("Unable to contact %q at %q, no IPv4 addresses to try as fallback",
thisRecord.Hostname, thisRecord.AddressesTried[0])
} else if len(v4) == 0 && len(thisRecord.AddressesTried) == 0 {
// It shouldn't be possible that there are no IPv4 addresses and no previous
// attempts at an IPv6 address connection but be defensive about it anyway
return nil, validationRecords, probs.Malformed(
fmt.Sprintf("No IP addresses found for %q", thisRecord.Hostname))
return nil, validationRecords, probs.Malformed("No IP addresses found for %q", thisRecord.Hostname)
}
// Otherwise if there are no IPv6 addresses, or there was an error
@ -578,13 +572,11 @@ func (va *ValidationAuthorityImpl) validateTLSSNI01WithZName(ctx context.Context
hostPort := net.JoinHostPort(validationRecords[0].AddressUsed.String(), validationRecords[0].Port)
names := certNames(leafCert)
errText := fmt.Sprintf(
"Incorrect validation certificate for %s challenge. "+
"Requested %s from %s. Received %d certificate(s), "+
"first certificate had names %q",
problem = probs.Unauthorized("Incorrect validation certificate for %s challenge. "+
"Requested %s from %s. Received %d certificate(s), first certificate had names %q",
challenge.Type, zName, hostPort, len(certs), strings.Join(names, ", "))
va.log.Infof("Remote host failed to give %s challenge name. host: %s", challenge.Type, identifier)
return validationRecords, probs.Unauthorized(errText)
return validationRecords, problem
}
func (va *ValidationAuthorityImpl) getTLSSNICerts(
@ -609,7 +601,7 @@ func (va *ValidationAuthorityImpl) getTLSSNICerts(
certs := conn.ConnectionState().PeerCertificates
if len(certs) == 0 {
va.log.Infof("%s challenge for %s resulted in no certificates", challenge.Type, identifier.Value)
return nil, probs.Unauthorized(fmt.Sprintf("No certs presented for %s challenge", challenge.Type))
return nil, probs.Unauthorized("No certs presented for %s challenge", challenge.Type)
}
for i, cert := range certs {
va.log.AuditInfof("%s challenge for %s received certificate (%d of %d): cert=[%s]",
@ -663,10 +655,10 @@ func (va *ValidationAuthorityImpl) validateHTTP01(ctx context.Context, identifie
payload := strings.TrimRight(string(body), whitespaceCutset)
if payload != challenge.ProvidedKeyAuthorization {
errString := fmt.Sprintf("The key authorization file from the server did not match this challenge [%v] != [%v]",
problem := probs.Unauthorized("The key authorization file from the server did not match this challenge [%v] != [%v]",
challenge.ProvidedKeyAuthorization, payload)
va.log.Infof("%s for %s", errString, identifier)
return validationRecords, probs.Unauthorized(errString)
va.log.Infof("%s for %s", problem.Detail, identifier)
return validationRecords, problem
}
return validationRecords, nil
@ -704,7 +696,7 @@ func detailedError(err error) *probs.ProblemDetails {
}
if tlsErr, ok := err.(tls.RecordHeaderError); ok && bytes.Compare(tlsErr.RecordHeader[:], badTLSHeader) == 0 {
return probs.Malformed(fmt.Sprintf("Server only speaks HTTP, not TLS"))
return probs.Malformed("Server only speaks HTTP, not TLS")
}
if netErr, ok := err.(*net.OpError); ok {
@ -724,7 +716,7 @@ func detailedError(err error) *probs.ProblemDetails {
} else if netErr.Timeout() && netErr.Op == "dial" {
return probs.ConnectionFailure("Timeout during connect (likely firewall problem)")
} else if netErr.Timeout() {
return probs.ConnectionFailure(fmt.Sprintf("Timeout during %s (your server may be slow or overloaded)", netErr.Op))
return probs.ConnectionFailure("Timeout during %s (your server may be slow or overloaded)", netErr.Op)
}
}
if err, ok := err.(net.Error); ok && err.Timeout() {
@ -761,8 +753,7 @@ func (va *ValidationAuthorityImpl) validateDNS01(ctx context.Context, identifier
// troubleshooters to differentiate between no TXT records and
// invalid/incorrect TXT records.
if len(txts) == 0 {
return nil, probs.Unauthorized(fmt.Sprintf(
"No TXT record found at %s", challengeSubdomain))
return nil, probs.Unauthorized("No TXT record found at %s", challengeSubdomain)
}
for _, element := range txts {
@ -783,9 +774,8 @@ func (va *ValidationAuthorityImpl) validateDNS01(ctx context.Context, identifier
if len(txts) > 1 {
andMore = fmt.Sprintf(" (and %d more)", len(txts)-1)
}
return nil, probs.Unauthorized(fmt.Sprintf(
"Incorrect TXT record %q%s found at %s",
invalidRecord, andMore, challengeSubdomain))
return nil, probs.Unauthorized("Incorrect TXT record %q%s found at %s",
invalidRecord, andMore, challengeSubdomain)
}
// validateChallengeAndIdentifier performs a challenge validation and, in parallel,
@ -815,9 +805,8 @@ func (va *ValidationAuthorityImpl) validateChallengeAndIdentifier(
}()
go func() {
if features.Enabled(features.VAChecksGSB) && !va.isSafeDomain(ctx, baseIdentifier.Value) {
ch <- probs.Unauthorized(fmt.Sprintf(
"%q was considered an unsafe domain by a third-party API",
baseIdentifier.Value))
ch <- probs.Unauthorized("%q was considered an unsafe domain by a third-party API",
baseIdentifier.Value)
} else {
ch <- nil
}
@ -850,7 +839,7 @@ func (va *ValidationAuthorityImpl) validateChallenge(ctx context.Context, identi
case core.ChallengeTypeDNS01:
return va.validateDNS01(ctx, identifier, challenge)
}
return nil, probs.Malformed(fmt.Sprintf("invalid challenge type %s", challenge.Type))
return nil, probs.Malformed("invalid challenge type %s", challenge.Type)
}
func (va *ValidationAuthorityImpl) performRemoteValidation(ctx context.Context, domain string, challenge core.Challenge, authz core.Authorization, result chan *probs.ProblemDetails) {

View File

@ -1,8 +1,6 @@
package web
import (
"fmt"
berrors "github.com/letsencrypt/boulder/errors"
"github.com/letsencrypt/boulder/probs"
)
@ -10,29 +8,29 @@ import (
func problemDetailsForBoulderError(err *berrors.BoulderError, msg string) *probs.ProblemDetails {
switch err.Type {
case berrors.Malformed:
return probs.Malformed(fmt.Sprintf("%s :: %s", msg, err))
return probs.Malformed("%s :: %s", msg, err)
case berrors.Unauthorized:
return probs.Unauthorized(fmt.Sprintf("%s :: %s", msg, err))
return probs.Unauthorized("%s :: %s", msg, err)
case berrors.NotFound:
return probs.NotFound(fmt.Sprintf("%s :: %s", msg, err))
return probs.NotFound("%s :: %s", msg, err)
case berrors.RateLimit:
return probs.RateLimited(fmt.Sprintf("%s :: %s", msg, err))
return probs.RateLimited("%s :: %s", msg, err)
case berrors.InternalServer:
// Internal server error messages may include sensitive data, so we do
// not include it.
return probs.ServerInternal(msg)
case berrors.RejectedIdentifier:
return probs.RejectedIdentifier(fmt.Sprintf("%s :: %s", msg, err))
return probs.RejectedIdentifier("%s :: %s", msg, err)
case berrors.InvalidEmail:
return probs.InvalidEmail(fmt.Sprintf("%s :: %s", msg, err))
return probs.InvalidEmail("%s :: %s", msg, err)
case berrors.WrongAuthorizationState:
return probs.Malformed(fmt.Sprintf("%s :: %s", msg, err))
return probs.Malformed("%s :: %s", msg, err)
case berrors.CAA:
return probs.CAA(fmt.Sprintf("%s :: %s", msg, err))
return probs.CAA("%s :: %s", msg, err)
case berrors.MissingSCTs:
// MissingSCTs are an internal server error, but with a specific error
// message related to the SCT problem
return probs.ServerInternal(fmt.Sprintf("%s :: %s", msg, "Unable to meet CA SCT embedding requirements"))
return probs.ServerInternal("%s :: %s", msg, "Unable to meet CA SCT embedding requirements")
default:
// Internal server error messages may include sensitive data, so we do
// not include it.

View File

@ -509,7 +509,7 @@ func (wfe *WebFrontEndImpl) verifyPOST(ctx context.Context, logEvent *web.Reques
// Only check for validity if we are actually checking the registration
if regCheck && reg.Status != core.StatusValid {
return nil, nil, reg, probs.Unauthorized(fmt.Sprintf("Registration is not valid, has status '%s'", reg.Status))
return nil, nil, reg, probs.Unauthorized("Registration is not valid, has status '%s'", reg.Status)
}
if statName, err := checkAlgorithm(key, parsedJws); err != nil {
@ -536,7 +536,7 @@ func (wfe *WebFrontEndImpl) verifyPOST(ctx context.Context, logEvent *web.Reques
return nil, nil, reg, probs.BadNonce("JWS has no anti-replay nonce")
} else if !wfe.nonceService.Valid(nonce) {
wfe.stats.Inc("Errors.JWSInvalidNonce", 1)
return nil, nil, reg, probs.BadNonce(fmt.Sprintf("JWS has invalid anti-replay nonce %s", nonce))
return nil, nil, reg, probs.BadNonce("JWS has invalid anti-replay nonce %s", nonce)
}
// Check that the "resource" field is present and has the correct value
@ -1164,8 +1164,8 @@ func (wfe *WebFrontEndImpl) Registration(ctx context.Context, logEvent *web.Requ
// extraneous requests to the RA we have to add this bypass.
if len(update.Agreement) > 0 && update.Agreement != currReg.Agreement &&
update.Agreement != wfe.SubscriberAgreementURL {
msg := fmt.Sprintf("Provided agreement URL [%s] does not match current agreement URL [%s]", update.Agreement, wfe.SubscriberAgreementURL)
wfe.sendError(response, logEvent, probs.Malformed(msg), nil)
problem := probs.Malformed("Provided agreement URL [%s] does not match current agreement URL [%s]", update.Agreement, wfe.SubscriberAgreementURL)
wfe.sendError(response, logEvent, problem, nil)
return
}

View File

@ -100,8 +100,7 @@ func checkJWSAuthType(jws *jose.JSONWebSignature) (jwsAuthType, *probs.ProblemDe
header := jws.Signatures[0].Header
// There must not be a Key ID *and* an embedded JWK
if header.KeyID != "" && header.JSONWebKey != nil {
return invalidAuthType, probs.Malformed(
"jwk and kid header fields are mutually exclusive")
return invalidAuthType, probs.Malformed("jwk and kid header fields are mutually exclusive")
} else if header.KeyID != "" {
return embeddedKeyID, nil
} else if header.JSONWebKey != nil {
@ -151,15 +150,13 @@ func (wfe *WebFrontEndImpl) validPOSTRequest(request *http.Request) *probs.Probl
// JSON serialization.
if _, present := request.Header["Content-Type"]; !present {
wfe.stats.httpErrorCount.With(prometheus.Labels{"type": "NoContentType"}).Inc()
return probs.InvalidContentType(fmt.Sprintf(
"No Content-Type header on POST. "+
"Content-Type must be %q", expectedJWSContentType))
return probs.InvalidContentType("No Content-Type header on POST. Content-Type must be %q",
expectedJWSContentType)
}
if contentType := request.Header.Get("Content-Type"); contentType != expectedJWSContentType {
wfe.stats.httpErrorCount.With(prometheus.Labels{"type": "WrongContentType"}).Inc()
return probs.InvalidContentType(fmt.Sprintf(
"Invalid Content-Type header on POST. "+
"Content-Type must be %q", expectedJWSContentType))
return probs.InvalidContentType("Invalid Content-Type header on POST. Content-Type must be %q",
expectedJWSContentType)
}
}
@ -193,7 +190,7 @@ func (wfe *WebFrontEndImpl) validNonce(jws *jose.JSONWebSignature) *probs.Proble
return probs.BadNonce("JWS has no anti-replay nonce")
} else if !wfe.nonceService.Valid(nonce) {
wfe.stats.joseErrorCount.With(prometheus.Labels{"type": "JWSInvalidNonce"}).Inc()
return probs.BadNonce(fmt.Sprintf("JWS has an invalid anti-replay nonce: %q", nonce))
return probs.BadNonce("JWS has an invalid anti-replay nonce: %q", nonce)
}
return nil
}
@ -230,9 +227,8 @@ func (wfe *WebFrontEndImpl) validPOSTURL(
// header
if expectedURL.String() != headerURL {
wfe.stats.joseErrorCount.With(prometheus.Labels{"type": "JWSMismatchedURL"}).Inc()
return probs.Malformed(fmt.Sprintf(
"JWS header parameter 'url' incorrect. Expected %q got %q",
expectedURL.String(), headerURL))
return probs.Malformed("JWS header parameter 'url' incorrect. Expected %q got %q",
expectedURL.String(), headerURL)
}
return nil
}
@ -262,9 +258,8 @@ func (wfe *WebFrontEndImpl) matchJWSURLs(outer, inner *jose.JSONWebSignature) *p
// Verify that the outer URL matches the inner URL
if outerURL != innerURL {
wfe.stats.joseErrorCount.With(prometheus.Labels{"type": "KeyRolloverMismatchedURLs"}).Inc()
return probs.Malformed(fmt.Sprintf(
"Outer JWS 'url' value %q does not match inner JWS 'url' value %q",
outerURL, innerURL))
return probs.Malformed("Outer JWS 'url' value %q does not match inner JWS 'url' value %q",
outerURL, innerURL)
}
return nil
@ -295,7 +290,7 @@ func (wfe *WebFrontEndImpl) parseJWS(body []byte) (*jose.JSONWebSignature, *prob
if unprotected.Header != nil {
wfe.stats.joseErrorCount.With(prometheus.Labels{"type": "JWSUnprotectedHeaders"}).Inc()
return nil, probs.Malformed(
"JWS \"header\" field not allowed. All headers must be in \"protected\" field")
`JWS "header" field not allowed. All headers must be in "protected" field`)
}
// ACME v2 never uses the "signatures" array of JSON serialized JWS, just the
@ -303,7 +298,7 @@ func (wfe *WebFrontEndImpl) parseJWS(body []byte) (*jose.JSONWebSignature, *prob
if len(unprotected.Signatures) > 0 {
wfe.stats.joseErrorCount.With(prometheus.Labels{"type": "JWSMultiSig"}).Inc()
return nil, probs.Malformed(
"JWS \"signatures\" field not allowed. Only the \"signature\" field should contain a signature")
`JWS "signatures" field not allowed. Only the "signature" field should contain a signature`)
}
// Parse the JWS using go-jose and enforce that the expected one non-empty
@ -402,7 +397,7 @@ func (wfe *WebFrontEndImpl) lookupJWK(
accountID, err := strconv.ParseInt(accountIDStr, 10, 64)
if err != nil {
wfe.stats.joseErrorCount.With(prometheus.Labels{"type": "JWSInvalidKeyID"}).Inc()
return nil, nil, probs.Malformed(fmt.Sprintf("Malformed account ID in KeyID header"))
return nil, nil, probs.Malformed("Malformed account ID in KeyID header")
}
// Try to find the account for this account ID
@ -411,8 +406,7 @@ func (wfe *WebFrontEndImpl) lookupJWK(
// If the account isn't found, return a suitable problem
if berrors.Is(err, berrors.NotFound) {
wfe.stats.joseErrorCount.With(prometheus.Labels{"type": "JWSKeyIDNotFound"}).Inc()
return nil, nil, probs.AccountDoesNotExist(fmt.Sprintf(
"Account %q not found", accountURL))
return nil, nil, probs.AccountDoesNotExist("Account %q not found", accountURL)
}
// If there was an error and it isn't a "Not Found" error, return
@ -420,15 +414,13 @@ func (wfe *WebFrontEndImpl) lookupJWK(
wfe.stats.joseErrorCount.With(prometheus.Labels{"type": "JWSKeyIDLookupFailed"}).Inc()
// Add an error to the log event with the internal error message
logEvent.AddError(fmt.Sprintf("Error calling SA.GetRegistration: %s", err.Error()))
return nil, nil, probs.ServerInternal(fmt.Sprintf(
"Error retreiving account %q", accountURL))
return nil, nil, probs.ServerInternal("Error retreiving account %q", accountURL)
}
// Verify the account is not deactivated
if account.Status != core.StatusValid {
wfe.stats.joseErrorCount.With(prometheus.Labels{"type": "JWSKeyIDAccountInvalid"}).Inc()
return nil, nil, probs.Unauthorized(
fmt.Sprintf("Account is not valid, has status %q", account.Status))
return nil, nil, probs.Unauthorized("Account is not valid, has status %q", account.Status)
}
// Update the logEvent with the account information and return the JWK

View File

@ -1599,15 +1599,15 @@ func (wfe *WebFrontEndImpl) GetOrder(ctx context.Context, logEvent *web.RequestE
order, err := wfe.SA.GetOrder(ctx, &sapb.OrderRequest{Id: &orderID})
if err != nil {
if berrors.Is(err, berrors.NotFound) {
wfe.sendError(response, logEvent, probs.NotFound(fmt.Sprintf("No order for ID %d", orderID)), err)
wfe.sendError(response, logEvent, probs.NotFound("No order for ID %d", orderID), err)
return
}
wfe.sendError(response, logEvent, probs.ServerInternal(fmt.Sprintf("Failed to retrieve order for ID %d", orderID)), err)
wfe.sendError(response, logEvent, probs.ServerInternal("Failed to retrieve order for ID %d", orderID), err)
return
}
if *order.RegistrationID != acctID {
wfe.sendError(response, logEvent, probs.NotFound(fmt.Sprintf("No order found for account ID %d", acctID)), nil)
wfe.sendError(response, logEvent, probs.NotFound("No order found for account ID %d", acctID), nil)
return
}
@ -1653,22 +1653,22 @@ func (wfe *WebFrontEndImpl) FinalizeOrder(ctx context.Context, logEvent *web.Req
order, err := wfe.SA.GetOrder(ctx, &sapb.OrderRequest{Id: &orderID})
if err != nil {
if berrors.Is(err, berrors.NotFound) {
wfe.sendError(response, logEvent, probs.NotFound(fmt.Sprintf("No order for ID %d", orderID)), err)
wfe.sendError(response, logEvent, probs.NotFound("No order for ID %d", orderID), err)
return
}
wfe.sendError(response, logEvent, probs.ServerInternal(fmt.Sprintf("Failed to retrieve order for ID %d", orderID)), err)
wfe.sendError(response, logEvent, probs.ServerInternal("Failed to retrieve order for ID %d", orderID), err)
return
}
if *order.RegistrationID != acctID {
wfe.sendError(response, logEvent, probs.NotFound(fmt.Sprintf("No order found for account ID %d", acctID)), nil)
wfe.sendError(response, logEvent, probs.NotFound("No order found for account ID %d", acctID), nil)
return
}
// If the authenticated account ID doesn't match the order's registration ID
// pretend it doesn't exist and abort.
if acct.ID != *order.RegistrationID {
wfe.sendError(response, logEvent, probs.NotFound(fmt.Sprintf("No order found for account ID %d", acct.ID)), nil)
wfe.sendError(response, logEvent, probs.NotFound("No order found for account ID %d", acct.ID), nil)
return
}
@ -1691,7 +1691,7 @@ func (wfe *WebFrontEndImpl) FinalizeOrder(ctx context.Context, logEvent *web.Req
// If the order is expired we can not finalize it and must return an error
orderExpiry := time.Unix(*order.Expires, 0)
if orderExpiry.Before(wfe.clk.Now()) {
wfe.sendError(response, logEvent, probs.NotFound(fmt.Sprintf("Order %d is expired", *order.Id)), nil)
wfe.sendError(response, logEvent, probs.NotFound("Order %d is expired", *order.Id), nil)
return
}