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:
parent
087074c73b
commit
9990d14654
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
65
va/va.go
65
va/va.go
|
@ -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) {
|
||||
|
|
20
web/probs.go
20
web/probs.go
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
16
wfe2/wfe.go
16
wfe2/wfe.go
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue