Skip to content

Commit 81eed0c

Browse files
authored
Replace invalid UTF-8 in error message (letsencrypt#5341)
Add processing to http body when it is passed as an error to be properly marshalled for grpc. Fixes letsencrypt#5317
1 parent 63d4a50 commit 81eed0c

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

va/http.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ func (va *ValidationAuthorityImpl) processHTTPValidation(
616616
// resulting payload is the same size as maxResponseSize fail
617617
if len(body) >= maxResponseSize {
618618
return nil, records, berrors.UnauthorizedError("Invalid response from %s [%s]: %q",
619-
records[len(records)-1].URL, records[len(records)-1].AddressUsed, body)
619+
records[len(records)-1].URL, records[len(records)-1].AddressUsed, replaceInvalidUTF8(body))
620620
}
621621
if httpResponse.StatusCode != 200 {
622622
return nil, records, berrors.UnauthorizedError("Invalid response from %s [%s]: %d",

va/http_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,20 @@ func httpTestSrv(t *testing.T) *httptest.Server {
579579
fmt.Fprint(resp, tooLargeBuf)
580580
})
581581

582+
// Create a buffer that starts with invalid UTF8 and is bigger than
583+
// maxResponseSize
584+
tooLargeInvalidUTF8 := bytes.NewBuffer([]byte{})
585+
tooLargeInvalidUTF8.WriteString("f\xffoo")
586+
tooLargeInvalidUTF8.Write(tooLargeBuf.Bytes())
587+
// invalid-utf8-body Responds with body that is larger than
588+
// maxResponseSize and starts with an invalid UTF8 string. This is to
589+
// test the codepath where invalid UTF8 is converted to valid UTF8
590+
// that can be passed as an error message via grpc.
591+
mux.HandleFunc("/invalid-utf8-body", func(resp http.ResponseWriter, req *http.Request) {
592+
resp.WriteHeader(http.StatusOK)
593+
fmt.Fprint(resp, tooLargeInvalidUTF8)
594+
})
595+
582596
mux.HandleFunc("/redir-path-too-long", func(resp http.ResponseWriter, req *http.Request) {
583597
http.Redirect(
584598
resp,
@@ -1049,6 +1063,23 @@ func TestFetchHTTP(t *testing.T) {
10491063
}
10501064
}
10511065

1066+
func TestFetchHTTPInvalidUTF8(t *testing.T) {
1067+
testSrv := httpTestSrv(t)
1068+
defer testSrv.Close()
1069+
va, _ := setup(testSrv, 0, "", nil)
1070+
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*500)
1071+
defer cancel()
1072+
_, _, prob := va.fetchHTTP(ctx, "example.com", "/invalid-utf8-body")
1073+
expectedResult := "f\ufffdoo"
1074+
// If the body of the http response is larger than the maxResponseSize
1075+
// a truncated body is returned as part of the error detail. If the
1076+
// body contains invalid UTF-8 the invalid characters must be replaced
1077+
// before the error is marshalled for grpc. This tests that the
1078+
// invalid string "f\xffoo" is expected to be converted to
1079+
// "f\ufffdoo".
1080+
test.AssertContains(t, string(prob.Detail), expectedResult)
1081+
}
1082+
10521083
// All paths that get assigned to tokens MUST be valid tokens
10531084
const pathWrongToken = "i6lNAC4lOOLYCl-A08VJt9z_tKYvVk63Dumo8icsBjQ"
10541085
const path404 = "404"

0 commit comments

Comments
 (0)