From d9a303c2341d7ea55b6a4c42fc970e8be5523401 Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Fri, 23 Feb 2024 15:41:22 -0500 Subject: [PATCH 01/18] lint: fix S1039 unnecessary Sprintf --- va/va.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/va/va.go b/va/va.go index 13e5d172..0a87d617 100644 --- a/va/va.go +++ b/va/va.go @@ -318,7 +318,7 @@ func (va VAImpl) validateDNS01(task *vaTask) *core.ValidationRecord { } if len(txts) == 0 { - msg := fmt.Sprintf("No TXT records found for DNS challenge") + msg := "No TXT records found for DNS challenge" result.Error = acme.UnauthorizedProblem(msg) return result } @@ -335,7 +335,7 @@ func (va VAImpl) validateDNS01(task *vaTask) *core.ValidationRecord { } } - msg := fmt.Sprintf("Correct value not found for DNS challenge") + msg := "Correct value not found for DNS challenge" result.Error = acme.UnauthorizedProblem(msg) return result } From 4b5f8c54c0a664dbb25aff7d1d0724574b9b8b24 Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Fri, 23 Feb 2024 15:53:06 -0500 Subject: [PATCH 02/18] lint: fix SA1019 deprecated RNG initialization --- cmd/pebble/main.go | 12 +++++++++-- wfe/wfe.go | 52 +++++++++++++++++++++++----------------------- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/cmd/pebble/main.go b/cmd/pebble/main.go index 259fda81..27f13dfa 100644 --- a/cmd/pebble/main.go +++ b/cmd/pebble/main.go @@ -3,9 +3,11 @@ package main import ( "flag" "log" + "math/rand" "net/http" "os" "strconv" + "time" "github.com/letsencrypt/pebble/v2/ca" "github.com/letsencrypt/pebble/v2/cmd" @@ -30,7 +32,7 @@ type config struct { DomainBlocklist []string CertificateValidityPeriod uint64 - RetryAfter struct { + RetryAfter struct { Authz int Order int } @@ -75,6 +77,11 @@ func main() { chainLength = int(val) } + // Initialize the randomness source + src := rand.NewSource(time.Now().UnixNano()) + rnd := rand.New(src) + + // Create the database, CA and VA instances db := db.NewMemoryStore() ca := ca.New(logger, db, c.Pebble.OCSPResponderURL, alternateRoots, chainLength, c.Pebble.CertificateValidityPeriod) va := va.New(logger, c.Pebble.HTTPPort, c.Pebble.TLSPort, *strictMode, *resolverAddress) @@ -89,7 +96,8 @@ func main() { cmd.FailOnError(err, "Failed to add domain to block list") } - wfeImpl := wfe.New(logger, db, va, ca, *strictMode, c.Pebble.ExternalAccountBindingRequired, c.Pebble.RetryAfter.Authz, c.Pebble.RetryAfter.Order) + // Create the WFE instance + wfeImpl := wfe.New(logger, db, va, ca, rnd, *strictMode, c.Pebble.ExternalAccountBindingRequired, c.Pebble.RetryAfter.Authz, c.Pebble.RetryAfter.Order) muxHandler := wfeImpl.Handler() if c.Pebble.ManagementListenAddress != "" { diff --git a/wfe/wfe.go b/wfe/wfe.go index 314f07b2..bcb6dc7d 100644 --- a/wfe/wfe.go +++ b/wfe/wfe.go @@ -162,6 +162,7 @@ type WebFrontEndImpl struct { ordersPerPage int va *va.VAImpl ca *ca.CAImpl + rnd *rand.Rand strict bool requireEAB bool retryAfterAuthz int @@ -175,10 +176,11 @@ func New( db *db.MemoryStore, va *va.VAImpl, ca *ca.CAImpl, - strict, requireEAB bool, retryAfterAuthz int, retryAfterOrder int) WebFrontEndImpl { - // Seed rand from the current time so test environments don't always have - // the same nonce rejection and sleep time patterns. - rand.Seed(time.Now().UnixNano()) + rnd *rand.Rand, + strict, + requireEAB bool, + retryAfterAuthz int, + retryAfterOrder int) WebFrontEndImpl { // Read the % of good nonces that should be rejected as bad nonces from the // environment @@ -234,6 +236,7 @@ func New( ordersPerPage: ordersPerPage, va: va, ca: ca, + rnd: rnd, strict: strict, requireEAB: requireEAB, retryAfterAuthz: retryAfterAuthz, @@ -906,7 +909,8 @@ func (wfe *WebFrontEndImpl) verifyJWS( } // Roll a random number between 0 and 100. - nonceRoll := rand.Intn(100) + nonceRoll := wfe.rnd.Intn(100) + // If the nonce is not valid OR if the nonceRoll was less than the // nonceErrPercent, fail with an error if !wfe.nonce.validNonce(nonce) || nonceRoll < wfe.nonceErrPercent { @@ -1402,11 +1406,10 @@ func isDNSCharacter(ch byte) bool { // validation is done on the order identifiers. func (wfe *WebFrontEndImpl) verifyOrder(order *core.Order) *acme.ProblemDetails { // Lock the order for reading - order.RLock() - defer order.RUnlock() - - // Shouldn't happen - defensive check - if order == nil { + if order != nil { + order.RLock() + defer order.RUnlock() + } else { return acme.InternalErrorProblem("Order is nil") } idents := order.Identifiers @@ -1440,8 +1443,7 @@ func (wfe *WebFrontEndImpl) verifyOrder(order *core.Order) *acme.ProblemDetails func (wfe *WebFrontEndImpl) validateDNSName(ident acme.Identifier) *acme.ProblemDetails { rawDomain := ident.Value if rawDomain == "" { - return acme.MalformedProblem(fmt.Sprintf( - "Order included DNS identifier with empty value")) + return acme.MalformedProblem("Order included DNS identifier with empty value") } for _, ch := range []byte(rawDomain) { @@ -1516,7 +1518,7 @@ func (wfe *WebFrontEndImpl) makeAuthorizations(order *core.Order, request *http. // If there is an existing valid authz for this identifier, we can reuse it authz := wfe.db.FindValidAuthorization(order.AccountID, ident) // Otherwise create a new pending authz (and randomly not) - if authz == nil || rand.Intn(100) > wfe.authzReusePercent { + if authz == nil || wfe.rnd.Intn(100) > wfe.authzReusePercent { authz = &core.Authorization{ ID: newToken(), ExpiresDate: expires, @@ -1744,10 +1746,10 @@ func (wfe *WebFrontEndImpl) orderForDisplay( // Clients SHOULD NOT make any assumptions about the sort order of // "identifiers" or "authorizations" elements in the returned order // object. - rand.Shuffle(len(result.Authorizations), func(i, j int) { + wfe.rnd.Shuffle(len(result.Authorizations), func(i, j int) { result.Authorizations[i], result.Authorizations[j] = result.Authorizations[j], result.Authorizations[i] }) - rand.Shuffle(len(result.Identifiers), func(i, j int) { + wfe.rnd.Shuffle(len(result.Identifiers), func(i, j int) { result.Identifiers[i], result.Identifiers[j] = result.Identifiers[j], result.Identifiers[i] }) @@ -1803,7 +1805,7 @@ func (wfe *WebFrontEndImpl) Order( } if order.Status == acme.StatusProcessing { - addRetryAfterHeader(response, wfe.retryAfterOrder) + addRetryAfterHeader(response, wfe.retryAfterOrder, wfe.rnd) } // Prepare the order for display as JSON @@ -1986,7 +1988,7 @@ func (wfe *WebFrontEndImpl) FinalizeOrder( // Set the existingOrder to processing before displaying to the user existingOrder.Status = acme.StatusProcessing - addRetryAfterHeader(response, wfe.retryAfterOrder) + addRetryAfterHeader(response, wfe.retryAfterOrder, wfe.rnd) // Prepare the order for display as JSON orderReq := wfe.orderForDisplay(existingOrder, request) @@ -2002,7 +2004,7 @@ func (wfe *WebFrontEndImpl) FinalizeOrder( // prepAuthorizationForDisplay prepares the provided acme.Authorization for // display to an ACME client. It assumes the `authz` is already locked for // reading by the caller. -func prepAuthorizationForDisplay(authz *core.Authorization) acme.Authorization { +func prepAuthorizationForDisplay(authz *core.Authorization, rnd *rand.Rand) acme.Authorization { // Copy the authz to mutate and return result := authz.Authorization identVal := result.Identifier.Value @@ -2031,7 +2033,7 @@ func prepAuthorizationForDisplay(authz *core.Authorization) acme.Authorization { // Randomize the order of the challenges in the returned authorization. // Clients should not make any assumptions about the sort order. - rand.Shuffle(len(result.Challenges), func(i, j int) { + rnd.Shuffle(len(result.Challenges), func(i, j int) { result.Challenges[i], result.Challenges[j] = result.Challenges[j], result.Challenges[i] }) @@ -2122,7 +2124,7 @@ func (wfe *WebFrontEndImpl) Authz( challengeStatus := c.Status c.RUnlock() if challengeStatus == acme.StatusProcessing { - addRetryAfterHeader(response, wfe.retryAfterAuthz) + addRetryAfterHeader(response, wfe.retryAfterAuthz, wfe.rnd) break } } @@ -2132,7 +2134,7 @@ func (wfe *WebFrontEndImpl) Authz( err := wfe.writeJSONResponse( response, http.StatusOK, - prepAuthorizationForDisplay(authz)) + prepAuthorizationForDisplay(authz, wfe.rnd)) if err != nil { wfe.sendError(acme.InternalErrorProblem("Error marshaling authz"), response) return @@ -2362,9 +2364,7 @@ func (wfe *WebFrontEndImpl) updateChallenge( // If the identifier value is for a wildcard domain then strip the wildcard // prefix before dispatching the validation to ensure the base domain is // validated. - if strings.HasPrefix(ident.Value, "*.") { - ident.Value = strings.TrimPrefix(ident.Value, "*.") - } + ident.Value = strings.TrimPrefix(ident.Value, "*.") // Confirm challenge status again and update it immediately before sending it to the VA prob = nil @@ -2503,9 +2503,9 @@ func addNoCacheHeader(response http.ResponseWriter) { response.Header().Add("Cache-Control", "public, max-age=0, no-cache") } -func addRetryAfterHeader(response http.ResponseWriter, second int) { +func addRetryAfterHeader(response http.ResponseWriter, second int, rnd *rand.Rand) { if second > 0 { - if rand.Intn(2) == 0 { + if rnd.Intn(2) == 0 { response.Header().Add("Retry-After", strconv.Itoa(second)) } else { // IMF-fixdate From 7e0debe49fc111cc537da9e9945c550edf83c469 Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Fri, 23 Feb 2024 16:18:44 -0500 Subject: [PATCH 03/18] golanci-lint: use default configuration --- .golangci.yaml | 45 --------------------------------------------- 1 file changed, 45 deletions(-) delete mode 100644 .golangci.yaml diff --git a/.golangci.yaml b/.golangci.yaml deleted file mode 100644 index c1aee64f..00000000 --- a/.golangci.yaml +++ /dev/null @@ -1,45 +0,0 @@ -linters-settings: - gocyclo: - min-complexity: 25 - govet: - check-shadowing: false - misspell: - locale: "US" - -linters: - enable-all: true - disable: - - stylecheck - - gosec - - dupl - - maligned - - depguard - - lll - - prealloc - - scopelint - - gocritic - - gochecknoinits - - gochecknoglobals - - godox - - funlen - - wsl - - whitespace - - gomnd - - typecheck - - godot - - errname - - nlreturn - - wrapcheck - -issues: - exclude-use-default: true - max-per-linter: 0 - max-same-issues: 0 - # The following excludes are considered false-positives/known-OK. - exclude-rules: - - path: ca([/|\\])ca.go - text: 'type name will be used as ca.CAImpl by other packages, and that stutters; consider calling this Impl' - - path: va([/|\\])va.go - text: 'type name will be used as va.VAImpl by other packages, and that stutters; consider calling this Impl' - - path: wfe([/|\\])wfe.go - text: 'if` block ends with a `return` statement, so drop this `else` and outdent its block' From 4d64602e72964f5f9b9670b23bd557f2d1424623 Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Sat, 24 Feb 2024 14:26:11 -0500 Subject: [PATCH 04/18] Revert "lint: fix SA1019 deprecated RNG initialization" This reverts commit 8f5449f7df7f01dcc716431041235f740eb2fb9b. --- cmd/pebble/main.go | 12 ++--------- wfe/wfe.go | 52 +++++++++++++++++++++++----------------------- 2 files changed, 28 insertions(+), 36 deletions(-) diff --git a/cmd/pebble/main.go b/cmd/pebble/main.go index 27f13dfa..259fda81 100644 --- a/cmd/pebble/main.go +++ b/cmd/pebble/main.go @@ -3,11 +3,9 @@ package main import ( "flag" "log" - "math/rand" "net/http" "os" "strconv" - "time" "github.com/letsencrypt/pebble/v2/ca" "github.com/letsencrypt/pebble/v2/cmd" @@ -32,7 +30,7 @@ type config struct { DomainBlocklist []string CertificateValidityPeriod uint64 - RetryAfter struct { + RetryAfter struct { Authz int Order int } @@ -77,11 +75,6 @@ func main() { chainLength = int(val) } - // Initialize the randomness source - src := rand.NewSource(time.Now().UnixNano()) - rnd := rand.New(src) - - // Create the database, CA and VA instances db := db.NewMemoryStore() ca := ca.New(logger, db, c.Pebble.OCSPResponderURL, alternateRoots, chainLength, c.Pebble.CertificateValidityPeriod) va := va.New(logger, c.Pebble.HTTPPort, c.Pebble.TLSPort, *strictMode, *resolverAddress) @@ -96,8 +89,7 @@ func main() { cmd.FailOnError(err, "Failed to add domain to block list") } - // Create the WFE instance - wfeImpl := wfe.New(logger, db, va, ca, rnd, *strictMode, c.Pebble.ExternalAccountBindingRequired, c.Pebble.RetryAfter.Authz, c.Pebble.RetryAfter.Order) + wfeImpl := wfe.New(logger, db, va, ca, *strictMode, c.Pebble.ExternalAccountBindingRequired, c.Pebble.RetryAfter.Authz, c.Pebble.RetryAfter.Order) muxHandler := wfeImpl.Handler() if c.Pebble.ManagementListenAddress != "" { diff --git a/wfe/wfe.go b/wfe/wfe.go index bcb6dc7d..314f07b2 100644 --- a/wfe/wfe.go +++ b/wfe/wfe.go @@ -162,7 +162,6 @@ type WebFrontEndImpl struct { ordersPerPage int va *va.VAImpl ca *ca.CAImpl - rnd *rand.Rand strict bool requireEAB bool retryAfterAuthz int @@ -176,11 +175,10 @@ func New( db *db.MemoryStore, va *va.VAImpl, ca *ca.CAImpl, - rnd *rand.Rand, - strict, - requireEAB bool, - retryAfterAuthz int, - retryAfterOrder int) WebFrontEndImpl { + strict, requireEAB bool, retryAfterAuthz int, retryAfterOrder int) WebFrontEndImpl { + // Seed rand from the current time so test environments don't always have + // the same nonce rejection and sleep time patterns. + rand.Seed(time.Now().UnixNano()) // Read the % of good nonces that should be rejected as bad nonces from the // environment @@ -236,7 +234,6 @@ func New( ordersPerPage: ordersPerPage, va: va, ca: ca, - rnd: rnd, strict: strict, requireEAB: requireEAB, retryAfterAuthz: retryAfterAuthz, @@ -909,8 +906,7 @@ func (wfe *WebFrontEndImpl) verifyJWS( } // Roll a random number between 0 and 100. - nonceRoll := wfe.rnd.Intn(100) - + nonceRoll := rand.Intn(100) // If the nonce is not valid OR if the nonceRoll was less than the // nonceErrPercent, fail with an error if !wfe.nonce.validNonce(nonce) || nonceRoll < wfe.nonceErrPercent { @@ -1406,10 +1402,11 @@ func isDNSCharacter(ch byte) bool { // validation is done on the order identifiers. func (wfe *WebFrontEndImpl) verifyOrder(order *core.Order) *acme.ProblemDetails { // Lock the order for reading - if order != nil { - order.RLock() - defer order.RUnlock() - } else { + order.RLock() + defer order.RUnlock() + + // Shouldn't happen - defensive check + if order == nil { return acme.InternalErrorProblem("Order is nil") } idents := order.Identifiers @@ -1443,7 +1440,8 @@ func (wfe *WebFrontEndImpl) verifyOrder(order *core.Order) *acme.ProblemDetails func (wfe *WebFrontEndImpl) validateDNSName(ident acme.Identifier) *acme.ProblemDetails { rawDomain := ident.Value if rawDomain == "" { - return acme.MalformedProblem("Order included DNS identifier with empty value") + return acme.MalformedProblem(fmt.Sprintf( + "Order included DNS identifier with empty value")) } for _, ch := range []byte(rawDomain) { @@ -1518,7 +1516,7 @@ func (wfe *WebFrontEndImpl) makeAuthorizations(order *core.Order, request *http. // If there is an existing valid authz for this identifier, we can reuse it authz := wfe.db.FindValidAuthorization(order.AccountID, ident) // Otherwise create a new pending authz (and randomly not) - if authz == nil || wfe.rnd.Intn(100) > wfe.authzReusePercent { + if authz == nil || rand.Intn(100) > wfe.authzReusePercent { authz = &core.Authorization{ ID: newToken(), ExpiresDate: expires, @@ -1746,10 +1744,10 @@ func (wfe *WebFrontEndImpl) orderForDisplay( // Clients SHOULD NOT make any assumptions about the sort order of // "identifiers" or "authorizations" elements in the returned order // object. - wfe.rnd.Shuffle(len(result.Authorizations), func(i, j int) { + rand.Shuffle(len(result.Authorizations), func(i, j int) { result.Authorizations[i], result.Authorizations[j] = result.Authorizations[j], result.Authorizations[i] }) - wfe.rnd.Shuffle(len(result.Identifiers), func(i, j int) { + rand.Shuffle(len(result.Identifiers), func(i, j int) { result.Identifiers[i], result.Identifiers[j] = result.Identifiers[j], result.Identifiers[i] }) @@ -1805,7 +1803,7 @@ func (wfe *WebFrontEndImpl) Order( } if order.Status == acme.StatusProcessing { - addRetryAfterHeader(response, wfe.retryAfterOrder, wfe.rnd) + addRetryAfterHeader(response, wfe.retryAfterOrder) } // Prepare the order for display as JSON @@ -1988,7 +1986,7 @@ func (wfe *WebFrontEndImpl) FinalizeOrder( // Set the existingOrder to processing before displaying to the user existingOrder.Status = acme.StatusProcessing - addRetryAfterHeader(response, wfe.retryAfterOrder, wfe.rnd) + addRetryAfterHeader(response, wfe.retryAfterOrder) // Prepare the order for display as JSON orderReq := wfe.orderForDisplay(existingOrder, request) @@ -2004,7 +2002,7 @@ func (wfe *WebFrontEndImpl) FinalizeOrder( // prepAuthorizationForDisplay prepares the provided acme.Authorization for // display to an ACME client. It assumes the `authz` is already locked for // reading by the caller. -func prepAuthorizationForDisplay(authz *core.Authorization, rnd *rand.Rand) acme.Authorization { +func prepAuthorizationForDisplay(authz *core.Authorization) acme.Authorization { // Copy the authz to mutate and return result := authz.Authorization identVal := result.Identifier.Value @@ -2033,7 +2031,7 @@ func prepAuthorizationForDisplay(authz *core.Authorization, rnd *rand.Rand) acme // Randomize the order of the challenges in the returned authorization. // Clients should not make any assumptions about the sort order. - rnd.Shuffle(len(result.Challenges), func(i, j int) { + rand.Shuffle(len(result.Challenges), func(i, j int) { result.Challenges[i], result.Challenges[j] = result.Challenges[j], result.Challenges[i] }) @@ -2124,7 +2122,7 @@ func (wfe *WebFrontEndImpl) Authz( challengeStatus := c.Status c.RUnlock() if challengeStatus == acme.StatusProcessing { - addRetryAfterHeader(response, wfe.retryAfterAuthz, wfe.rnd) + addRetryAfterHeader(response, wfe.retryAfterAuthz) break } } @@ -2134,7 +2132,7 @@ func (wfe *WebFrontEndImpl) Authz( err := wfe.writeJSONResponse( response, http.StatusOK, - prepAuthorizationForDisplay(authz, wfe.rnd)) + prepAuthorizationForDisplay(authz)) if err != nil { wfe.sendError(acme.InternalErrorProblem("Error marshaling authz"), response) return @@ -2364,7 +2362,9 @@ func (wfe *WebFrontEndImpl) updateChallenge( // If the identifier value is for a wildcard domain then strip the wildcard // prefix before dispatching the validation to ensure the base domain is // validated. - ident.Value = strings.TrimPrefix(ident.Value, "*.") + if strings.HasPrefix(ident.Value, "*.") { + ident.Value = strings.TrimPrefix(ident.Value, "*.") + } // Confirm challenge status again and update it immediately before sending it to the VA prob = nil @@ -2503,9 +2503,9 @@ func addNoCacheHeader(response http.ResponseWriter) { response.Header().Add("Cache-Control", "public, max-age=0, no-cache") } -func addRetryAfterHeader(response http.ResponseWriter, second int, rnd *rand.Rand) { +func addRetryAfterHeader(response http.ResponseWriter, second int) { if second > 0 { - if rnd.Intn(2) == 0 { + if rand.Intn(2) == 0 { response.Header().Add("Retry-After", strconv.Itoa(second)) } else { // IMF-fixdate From 5933cda4c51cf90720325bf8d0f7d13c4297b84f Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Sat, 24 Feb 2024 17:13:44 -0500 Subject: [PATCH 05/18] lint: fix SA1019 deprecated RNG initialization avoiding data race --- wfe/wfe.go | 94 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 74 insertions(+), 20 deletions(-) diff --git a/wfe/wfe.go b/wfe/wfe.go index 314f07b2..5a0ea00b 100644 --- a/wfe/wfe.go +++ b/wfe/wfe.go @@ -176,9 +176,6 @@ func New( va *va.VAImpl, ca *ca.CAImpl, strict, requireEAB bool, retryAfterAuthz int, retryAfterOrder int) WebFrontEndImpl { - // Seed rand from the current time so test environments don't always have - // the same nonce rejection and sleep time patterns. - rand.Seed(time.Now().UnixNano()) // Read the % of good nonces that should be rejected as bad nonces from the // environment @@ -550,10 +547,13 @@ func (wfe *WebFrontEndImpl) Directory( "keyChange": keyRolloverPath, } + // Initialize local rnd + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + // RFC 8555 §6.3 says the server's directory endpoint should support // POST-as-GET as well as GET. if request.Method == http.MethodPost { - postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -631,10 +631,13 @@ func (wfe *WebFrontEndImpl) Nonce( statusCode = http.StatusOK } + // Initialize local rnd + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + // RFC 8555 §6.3 says the server's nonce endpoint should support // POST-as-GET as well as GET. if request.Method == http.MethodPost { - postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -824,10 +827,12 @@ type authenticatedPOST struct { jwk *jose.JSONWebKey } +// verifyPOST verifies that a POST request is valid. // NOTE: Unlike `verifyPOST` from the Boulder WFE this version does not // presently handle the `regCheck` parameter or do any lookups for existing // accounts. func (wfe *WebFrontEndImpl) verifyPOST( + rnd *rand.Rand, request *http.Request, kx keyExtractor) (*authenticatedPOST, *acme.ProblemDetails) { @@ -851,7 +856,7 @@ func (wfe *WebFrontEndImpl) verifyPOST( return nil, prob } - result, prob := wfe.verifyJWS(pubKey, parsedJWS, request) + result, prob := wfe.verifyJWS(rnd, pubKey, parsedJWS, request) if prob != nil { return nil, prob } @@ -887,6 +892,7 @@ func (wfe *WebFrontEndImpl) extractJWSURL( } func (wfe *WebFrontEndImpl) verifyJWS( + rnd *rand.Rand, pubKey *jose.JSONWebKey, parsedJWS *jose.JSONWebSignature, request *http.Request) (*authenticatedPOST, *acme.ProblemDetails) { @@ -906,7 +912,7 @@ func (wfe *WebFrontEndImpl) verifyJWS( } // Roll a random number between 0 and 100. - nonceRoll := rand.Intn(100) + nonceRoll := rnd.Intn(100) // If the nonce is not valid OR if the nonceRoll was less than the // nonceErrPercent, fail with an error if !wfe.nonce.validNonce(nonce) || nonceRoll < wfe.nonceErrPercent { @@ -1010,7 +1016,12 @@ func (wfe *WebFrontEndImpl) UpdateAccount( ctx context.Context, response http.ResponseWriter, request *http.Request) { - postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) + + // Initialize local rnd + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + + // Verify the request is valid + postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -1104,7 +1115,12 @@ func (wfe *WebFrontEndImpl) ListOrders( ctx context.Context, response http.ResponseWriter, request *http.Request) { - postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) + + // Initialize local rnd + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + + // Verify the request is valid + postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -1214,8 +1230,12 @@ func (wfe *WebFrontEndImpl) KeyRollover( ctx context.Context, response http.ResponseWriter, request *http.Request) { + + // Initialize local rnd + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + // Extract and parse outer JWS, and retrieve account - outerPostData, prob := wfe.verifyPOST(request, wfe.lookupJWK) + outerPostData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -1285,10 +1305,13 @@ func (wfe *WebFrontEndImpl) NewAccount( response http.ResponseWriter, request *http.Request) { + // Initialize local rnd + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + // We use extractJWK rather than lookupJWK here because the account is not yet // created, so the user provides the full key in a JWS header rather than // referring to an existing key. - postData, prob := wfe.verifyPOST(request, wfe.extractJWK) + postData, prob := wfe.verifyPOST(rnd, request, wfe.extractJWK) if prob != nil { wfe.sendError(prob, response) return @@ -1625,7 +1648,11 @@ func (wfe *WebFrontEndImpl) NewOrder( response http.ResponseWriter, request *http.Request) { - postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) + // Initialize local rnd + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + + // Verify the request is valid + postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -1771,7 +1798,12 @@ func (wfe *WebFrontEndImpl) Order( ctx context.Context, response http.ResponseWriter, request *http.Request) { - postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) + + // Initialize local rnd + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + + // Verify the request is valid + postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -1820,8 +1852,11 @@ func (wfe *WebFrontEndImpl) FinalizeOrder( response http.ResponseWriter, request *http.Request) { + // Initialize local rnd + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + // Verify the POST request - postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -2042,10 +2077,14 @@ func (wfe *WebFrontEndImpl) Authz( ctx context.Context, response http.ResponseWriter, request *http.Request) { + + // Initialize local rnd + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + // There are two types of requests we might get: // A) a POST to update the authorization // B) a POST-as-GET to get the authorization - postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -2143,10 +2182,14 @@ func (wfe *WebFrontEndImpl) Challenge( ctx context.Context, response http.ResponseWriter, request *http.Request) { + + // Initialize local rnd + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + // There are two possibilities: // A) request is a POST to begin a challenge // B) request is a POST-as-GET to poll a challenge - postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -2441,7 +2484,11 @@ func (wfe *WebFrontEndImpl) Certificate( ctx context.Context, response http.ResponseWriter, request *http.Request) { - postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) + // Initialize local rnd + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + + // Verify the request + postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -2626,12 +2673,15 @@ func (wfe *WebFrontEndImpl) revokeCertByKeyID( jws *jose.JSONWebSignature, request *http.Request) *acme.ProblemDetails { + // Initialize local rnd + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + + // Extract the JWK from the JWS and verify the JWS pubKey, prob := wfe.lookupJWK(request, jws) if prob != nil { return prob } - - postData, prob := wfe.verifyJWS(pubKey, jws, request) + postData, prob := wfe.verifyJWS(rnd, pubKey, jws, request) if prob != nil { return prob } @@ -2664,12 +2714,16 @@ func (wfe *WebFrontEndImpl) revokeCertByJWK( jws *jose.JSONWebSignature, request *http.Request) *acme.ProblemDetails { + // Initialize local rnd + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + + // Extract the JWK from the JWS and verify the JWS var requestKey *jose.JSONWebKey pubKey, prob := wfe.extractJWK(request, jws) if prob != nil { return prob } - postData, prob := wfe.verifyJWS(pubKey, jws, request) + postData, prob := wfe.verifyJWS(rnd, pubKey, jws, request) if prob != nil { return prob } From f27f47a153ab733b49ab494f9ba7133636e05732 Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Wed, 21 Feb 2024 17:20:19 -0500 Subject: [PATCH 06/18] install python requirements for chisel2 in Travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 2b5bcdb0..56c30249 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,6 +56,7 @@ script: # Upload collected coverage profile to goveralls - goveralls -coverprofile=coverage.out -service=travis-ci # Perform a test issuance with chisel2.py + - pip install -r test/requirements.txt - REQUESTS_CA_BUNDLE=./test/certs/pebble.minica.pem python ./test/chisel2.py example.letsencrypt.org elpmaxe.letsencrypt.org # Run the load-generator briefly - note, because Pebble isn't using the # load-generator's mock DNS server none of the issuances will succeed. This From 92da2fc9c0d218c50d24d0f09a9b4f20164849a7 Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Tue, 20 Feb 2024 10:03:04 -0500 Subject: [PATCH 07/18] Fix order is nil check --- wfe/wfe.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/wfe/wfe.go b/wfe/wfe.go index 5a0ea00b..9e6e6d8d 100644 --- a/wfe/wfe.go +++ b/wfe/wfe.go @@ -1424,14 +1424,15 @@ func isDNSCharacter(ch byte) bool { // verifyOrder checks that a new order is considered well formed. Light // validation is done on the order identifiers. func (wfe *WebFrontEndImpl) verifyOrder(order *core.Order) *acme.ProblemDetails { - // Lock the order for reading - order.RLock() - defer order.RUnlock() - // Shouldn't happen - defensive check if order == nil { return acme.InternalErrorProblem("Order is nil") } + + // Lock the order for reading + order.RLock() + defer order.RUnlock() + idents := order.Identifiers if len(idents) == 0 { return acme.MalformedProblem("Order did not specify any identifiers") From 2f325eaef731b4d1ead069b99c9b32d08e2e85c4 Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Tue, 20 Feb 2024 10:03:39 -0500 Subject: [PATCH 08/18] typo --- wfe/wfe.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wfe/wfe.go b/wfe/wfe.go index 9e6e6d8d..de01674b 100644 --- a/wfe/wfe.go +++ b/wfe/wfe.go @@ -605,7 +605,7 @@ func (wfe *WebFrontEndImpl) relativeEndpoint(request *http.Request, endpoint str proto = "https" } - // Allow upstream proxies to specify the forwarded protocol. Allow this value + // Allow upstream proxies to specify the forwarded protocol. Allow this value // to override our own guess. if specifiedProto := request.Header.Get("X-Forwarded-Proto"); specifiedProto != "" { proto = specifiedProto From 1575cd487526b509d13a68a387a0b269dd9f50ab Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Tue, 20 Feb 2024 16:43:58 -0500 Subject: [PATCH 09/18] fix(wfe): Use built-in UTC for TZ to eliminate panics --- wfe/wfe.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wfe/wfe.go b/wfe/wfe.go index de01674b..c0b47bab 100644 --- a/wfe/wfe.go +++ b/wfe/wfe.go @@ -2558,8 +2558,7 @@ func addRetryAfterHeader(response http.ResponseWriter, second int) { } else { // IMF-fixdate // see https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.1.1 - gmt, _ := time.LoadLocation("GMT") - currentTime := time.Now().In(gmt) + currentTime := time.Now().In(time.UTC) retryAfter := currentTime.Add(time.Second * time.Duration(second)) response.Header().Add("Retry-After", retryAfter.Format(http.TimeFormat)) } From a9d31c5316dd90bfd5b1ad86a753ed6e443768e8 Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Tue, 20 Feb 2024 17:00:51 -0500 Subject: [PATCH 10/18] remove unused pebble main_test.go --- cmd/pebble/main_test.go | 1 - 1 file changed, 1 deletion(-) delete mode 100644 cmd/pebble/main_test.go diff --git a/cmd/pebble/main_test.go b/cmd/pebble/main_test.go deleted file mode 100644 index 06ab7d0f..00000000 --- a/cmd/pebble/main_test.go +++ /dev/null @@ -1 +0,0 @@ -package main From 910c09ff7a0a28eb0ee44f53104481b6f030af3c Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Wed, 21 Feb 2024 16:27:45 -0500 Subject: [PATCH 11/18] fix appveyor with updates and x64 --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 0a3d92fb..acbbffb1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,11 +1,11 @@ -image: Visual Studio 2019 +image: Visual Studio 2022 hosts: example.letsencrypt.org: 127.0.0.1 elpmaxe.letsencrypt.org: 127.0.0.1 environment: - PATH: C:\Python38;C:\msys64\mingw64\bin;%USERPROFILE%\go\bin;%PATH% + PATH: C:\Python39-x64;C:\msys64\mingw64\bin;%USERPROFILE%\go\bin;%PATH% PEBBLE_WFE_NONCEREJECT: 0 # Declare artifacts that can become release assets on GitHub From b62c4fd0cd4b310eb5696d6d7b1c0c69e54ed098 Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Wed, 21 Feb 2024 17:22:06 -0500 Subject: [PATCH 12/18] update golangci-lint to current v1.56.2 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 56c30249..3dc1c19a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ before_install: # `-mod=vendor` to use the vendored dependencies install: # Install `golangci-lint` using their installer script - - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.45.2 + - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.56.2 # Install tools without `GO111MODULE` enabled so that we # don't download Pebble's deps and just put the tools in our # gobin. From e07b2ecec91fb03e0ef1e93c441c15a6fca77bce Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Sat, 24 Feb 2024 20:05:59 -0500 Subject: [PATCH 13/18] Revert "lint: fix SA1019 deprecated RNG initialization avoiding data race" This reverts commit fd2b2beaa84994e05329099ed1e4bca348ae9865. --- wfe/wfe.go | 94 ++++++++++++------------------------------------------ 1 file changed, 20 insertions(+), 74 deletions(-) diff --git a/wfe/wfe.go b/wfe/wfe.go index c0b47bab..8a1e41de 100644 --- a/wfe/wfe.go +++ b/wfe/wfe.go @@ -176,6 +176,9 @@ func New( va *va.VAImpl, ca *ca.CAImpl, strict, requireEAB bool, retryAfterAuthz int, retryAfterOrder int) WebFrontEndImpl { + // Seed rand from the current time so test environments don't always have + // the same nonce rejection and sleep time patterns. + rand.Seed(time.Now().UnixNano()) // Read the % of good nonces that should be rejected as bad nonces from the // environment @@ -547,13 +550,10 @@ func (wfe *WebFrontEndImpl) Directory( "keyChange": keyRolloverPath, } - // Initialize local rnd - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - // RFC 8555 §6.3 says the server's directory endpoint should support // POST-as-GET as well as GET. if request.Method == http.MethodPost { - postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -631,13 +631,10 @@ func (wfe *WebFrontEndImpl) Nonce( statusCode = http.StatusOK } - // Initialize local rnd - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - // RFC 8555 §6.3 says the server's nonce endpoint should support // POST-as-GET as well as GET. if request.Method == http.MethodPost { - postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -827,12 +824,10 @@ type authenticatedPOST struct { jwk *jose.JSONWebKey } -// verifyPOST verifies that a POST request is valid. // NOTE: Unlike `verifyPOST` from the Boulder WFE this version does not // presently handle the `regCheck` parameter or do any lookups for existing // accounts. func (wfe *WebFrontEndImpl) verifyPOST( - rnd *rand.Rand, request *http.Request, kx keyExtractor) (*authenticatedPOST, *acme.ProblemDetails) { @@ -856,7 +851,7 @@ func (wfe *WebFrontEndImpl) verifyPOST( return nil, prob } - result, prob := wfe.verifyJWS(rnd, pubKey, parsedJWS, request) + result, prob := wfe.verifyJWS(pubKey, parsedJWS, request) if prob != nil { return nil, prob } @@ -892,7 +887,6 @@ func (wfe *WebFrontEndImpl) extractJWSURL( } func (wfe *WebFrontEndImpl) verifyJWS( - rnd *rand.Rand, pubKey *jose.JSONWebKey, parsedJWS *jose.JSONWebSignature, request *http.Request) (*authenticatedPOST, *acme.ProblemDetails) { @@ -912,7 +906,7 @@ func (wfe *WebFrontEndImpl) verifyJWS( } // Roll a random number between 0 and 100. - nonceRoll := rnd.Intn(100) + nonceRoll := rand.Intn(100) // If the nonce is not valid OR if the nonceRoll was less than the // nonceErrPercent, fail with an error if !wfe.nonce.validNonce(nonce) || nonceRoll < wfe.nonceErrPercent { @@ -1016,12 +1010,7 @@ func (wfe *WebFrontEndImpl) UpdateAccount( ctx context.Context, response http.ResponseWriter, request *http.Request) { - - // Initialize local rnd - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - - // Verify the request is valid - postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -1115,12 +1104,7 @@ func (wfe *WebFrontEndImpl) ListOrders( ctx context.Context, response http.ResponseWriter, request *http.Request) { - - // Initialize local rnd - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - - // Verify the request is valid - postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -1230,12 +1214,8 @@ func (wfe *WebFrontEndImpl) KeyRollover( ctx context.Context, response http.ResponseWriter, request *http.Request) { - - // Initialize local rnd - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - // Extract and parse outer JWS, and retrieve account - outerPostData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) + outerPostData, prob := wfe.verifyPOST(request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -1305,13 +1285,10 @@ func (wfe *WebFrontEndImpl) NewAccount( response http.ResponseWriter, request *http.Request) { - // Initialize local rnd - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - // We use extractJWK rather than lookupJWK here because the account is not yet // created, so the user provides the full key in a JWS header rather than // referring to an existing key. - postData, prob := wfe.verifyPOST(rnd, request, wfe.extractJWK) + postData, prob := wfe.verifyPOST(request, wfe.extractJWK) if prob != nil { wfe.sendError(prob, response) return @@ -1649,11 +1626,7 @@ func (wfe *WebFrontEndImpl) NewOrder( response http.ResponseWriter, request *http.Request) { - // Initialize local rnd - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - - // Verify the request is valid - postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -1799,12 +1772,7 @@ func (wfe *WebFrontEndImpl) Order( ctx context.Context, response http.ResponseWriter, request *http.Request) { - - // Initialize local rnd - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - - // Verify the request is valid - postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -1853,11 +1821,8 @@ func (wfe *WebFrontEndImpl) FinalizeOrder( response http.ResponseWriter, request *http.Request) { - // Initialize local rnd - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - // Verify the POST request - postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -2078,14 +2043,10 @@ func (wfe *WebFrontEndImpl) Authz( ctx context.Context, response http.ResponseWriter, request *http.Request) { - - // Initialize local rnd - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - // There are two types of requests we might get: // A) a POST to update the authorization // B) a POST-as-GET to get the authorization - postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -2183,14 +2144,10 @@ func (wfe *WebFrontEndImpl) Challenge( ctx context.Context, response http.ResponseWriter, request *http.Request) { - - // Initialize local rnd - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - // There are two possibilities: // A) request is a POST to begin a challenge // B) request is a POST-as-GET to poll a challenge - postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -2485,11 +2442,7 @@ func (wfe *WebFrontEndImpl) Certificate( ctx context.Context, response http.ResponseWriter, request *http.Request) { - // Initialize local rnd - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - - // Verify the request - postData, prob := wfe.verifyPOST(rnd, request, wfe.lookupJWK) + postData, prob := wfe.verifyPOST(request, wfe.lookupJWK) if prob != nil { wfe.sendError(prob, response) return @@ -2673,15 +2626,12 @@ func (wfe *WebFrontEndImpl) revokeCertByKeyID( jws *jose.JSONWebSignature, request *http.Request) *acme.ProblemDetails { - // Initialize local rnd - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - - // Extract the JWK from the JWS and verify the JWS pubKey, prob := wfe.lookupJWK(request, jws) if prob != nil { return prob } - postData, prob := wfe.verifyJWS(rnd, pubKey, jws, request) + + postData, prob := wfe.verifyJWS(pubKey, jws, request) if prob != nil { return prob } @@ -2714,16 +2664,12 @@ func (wfe *WebFrontEndImpl) revokeCertByJWK( jws *jose.JSONWebSignature, request *http.Request) *acme.ProblemDetails { - // Initialize local rnd - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - - // Extract the JWK from the JWS and verify the JWS var requestKey *jose.JSONWebKey pubKey, prob := wfe.extractJWK(request, jws) if prob != nil { return prob } - postData, prob := wfe.verifyJWS(rnd, pubKey, jws, request) + postData, prob := wfe.verifyJWS(pubKey, jws, request) if prob != nil { return prob } From 000aa601d9b8f545b3fd59deff45c5e50824ff6e Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Sat, 24 Feb 2024 20:06:41 -0500 Subject: [PATCH 14/18] lint: fix SA1019 rand.Seed deprecation --- wfe/wfe.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/wfe/wfe.go b/wfe/wfe.go index 8a1e41de..3b25267d 100644 --- a/wfe/wfe.go +++ b/wfe/wfe.go @@ -176,9 +176,6 @@ func New( va *va.VAImpl, ca *ca.CAImpl, strict, requireEAB bool, retryAfterAuthz int, retryAfterOrder int) WebFrontEndImpl { - // Seed rand from the current time so test environments don't always have - // the same nonce rejection and sleep time patterns. - rand.Seed(time.Now().UnixNano()) // Read the % of good nonces that should be rejected as bad nonces from the // environment From ab7a2e9fe0dc28991a2eeb72b3af0d3c35f801e5 Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Sat, 24 Feb 2024 20:08:30 -0500 Subject: [PATCH 15/18] fix lint S1039: unnecessary use of fmt.Sprintf --- wfe/wfe.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wfe/wfe.go b/wfe/wfe.go index 3b25267d..1f4bef2f 100644 --- a/wfe/wfe.go +++ b/wfe/wfe.go @@ -1438,8 +1438,7 @@ func (wfe *WebFrontEndImpl) verifyOrder(order *core.Order) *acme.ProblemDetails func (wfe *WebFrontEndImpl) validateDNSName(ident acme.Identifier) *acme.ProblemDetails { rawDomain := ident.Value if rawDomain == "" { - return acme.MalformedProblem(fmt.Sprintf( - "Order included DNS identifier with empty value")) + return acme.MalformedProblem("Order included DNS identifier with empty value") } for _, ch := range []byte(rawDomain) { From 7ccbbc3868ff3d76b363dc186279451a86983b10 Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Sat, 24 Feb 2024 20:09:19 -0500 Subject: [PATCH 16/18] fix lint S1017: should replace this `if` statement with an unconditional `strings.TrimPrefix` (gosimple) --- wfe/wfe.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/wfe/wfe.go b/wfe/wfe.go index 1f4bef2f..531a4661 100644 --- a/wfe/wfe.go +++ b/wfe/wfe.go @@ -2359,9 +2359,7 @@ func (wfe *WebFrontEndImpl) updateChallenge( // If the identifier value is for a wildcard domain then strip the wildcard // prefix before dispatching the validation to ensure the base domain is // validated. - if strings.HasPrefix(ident.Value, "*.") { - ident.Value = strings.TrimPrefix(ident.Value, "*.") - } + ident.Value = strings.TrimPrefix(ident.Value, "*.") // Confirm challenge status again and update it immediately before sending it to the VA prob = nil From f5bcbb6b7ce7f4221df703ac60b71b7d85183444 Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Tue, 27 Feb 2024 10:46:47 -0500 Subject: [PATCH 17/18] Revert "golanci-lint: use default configuration" This reverts commit 7e0debe49fc111cc537da9e9945c550edf83c469. --- .golangci.yaml | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 .golangci.yaml diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 00000000..c1aee64f --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,45 @@ +linters-settings: + gocyclo: + min-complexity: 25 + govet: + check-shadowing: false + misspell: + locale: "US" + +linters: + enable-all: true + disable: + - stylecheck + - gosec + - dupl + - maligned + - depguard + - lll + - prealloc + - scopelint + - gocritic + - gochecknoinits + - gochecknoglobals + - godox + - funlen + - wsl + - whitespace + - gomnd + - typecheck + - godot + - errname + - nlreturn + - wrapcheck + +issues: + exclude-use-default: true + max-per-linter: 0 + max-same-issues: 0 + # The following excludes are considered false-positives/known-OK. + exclude-rules: + - path: ca([/|\\])ca.go + text: 'type name will be used as ca.CAImpl by other packages, and that stutters; consider calling this Impl' + - path: va([/|\\])va.go + text: 'type name will be used as va.VAImpl by other packages, and that stutters; consider calling this Impl' + - path: wfe([/|\\])wfe.go + text: 'if` block ends with a `return` statement, so drop this `else` and outdent its block' From 6c7d160f015f50d1d96cff23e53c02ae1404ae19 Mon Sep 17 00:00:00 2001 From: Shiloh Heurich Date: Tue, 27 Feb 2024 10:59:40 -0500 Subject: [PATCH 18/18] fix wfe/wfe.go:178: File is not `gofumpt`-ed (gofumpt) --- wfe/wfe.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wfe/wfe.go b/wfe/wfe.go index 94323b29..97c5be0a 100644 --- a/wfe/wfe.go +++ b/wfe/wfe.go @@ -175,8 +175,8 @@ func New( db *db.MemoryStore, va *va.VAImpl, ca *ca.CAImpl, - strict, requireEAB bool, retryAfterAuthz int, retryAfterOrder int) WebFrontEndImpl { - + strict, requireEAB bool, retryAfterAuthz int, retryAfterOrder int, +) WebFrontEndImpl { // Read the % of good nonces that should be rejected as bad nonces from the // environment nonceErrPercentVal := os.Getenv(badNonceEnvVar)