From: Damien Neil Date: Tue, 13 Oct 2020 20:02:45 +0000 (-0700) Subject: net/http: return 505 status for rejected protocol version X-Git-Tag: go1.16beta1~736 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=9c56300e62d126875dcd6508c0ca7dce3985ad50;p=gostls13.git net/http: return 505 status for rejected protocol version When rejecting a request with an unsupported HTTP protocol version, return a 505 error ("HTTP Version Not Supported") instead of 400. Fixes #40454. Change-Id: I0269f0f5755d90d1b772ba0094a6bb24b5eb4701 Reviewed-on: https://go-review.googlesource.com/c/go/+/261977 Trust: Damien Neil Run-TryBot: Damien Neil TryBot-Result: Go Bot Reviewed-by: Urban Ishimwe Reviewed-by: Brad Fitzpatrick --- diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 6d3317fb0c..cbd3101f27 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -4622,7 +4622,7 @@ func TestServerValidatesHostHeader(t *testing.T) { host string want int }{ - {"HTTP/0.9", "", 400}, + {"HTTP/0.9", "", 505}, {"HTTP/1.1", "", 400}, {"HTTP/1.1", "Host: \r\n", 200}, @@ -4654,9 +4654,9 @@ func TestServerValidatesHostHeader(t *testing.T) { {"CONNECT golang.org:443 HTTP/1.1", "", 200}, // But not other HTTP/2 stuff: - {"PRI / HTTP/2.0", "", 400}, - {"GET / HTTP/2.0", "", 400}, - {"GET / HTTP/3.0", "", 400}, + {"PRI / HTTP/2.0", "", 505}, + {"GET / HTTP/2.0", "", 505}, + {"GET / HTTP/3.0", "", 505}, } for _, tt := range tests { conn := &testConn{closec: make(chan bool, 1)} diff --git a/src/net/http/server.go b/src/net/http/server.go index 25fab288f2..db3a09b993 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -992,7 +992,7 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) { } if !http1ServerSupportsRequest(req) { - return nil, badRequestError("unsupported protocol version") + return nil, statusError{StatusHTTPVersionNotSupported, "unsupported protocol version"} } c.lastMethod = req.Method @@ -1773,9 +1773,16 @@ func (c *conn) getState() (state ConnState, unixSec int64) { // badRequestError is a literal string (used by in the server in HTML, // unescaped) to tell the user why their request was bad. It should // be plain text without user info or other embedded errors. -type badRequestError string +func badRequestError(e string) error { return statusError{StatusBadRequest, e} } -func (e badRequestError) Error() string { return "Bad Request: " + string(e) } +// statusError is an error used to respond to a request with an HTTP status. +// The text should be plain text without user info or other embedded errors. +type statusError struct { + code int + text string +} + +func (e statusError) Error() string { return StatusText(e.code) + ": " + e.text } // ErrAbortHandler is a sentinel panic value to abort a handler. // While any panic from ServeHTTP aborts the response to the client, @@ -1898,11 +1905,11 @@ func (c *conn) serve(ctx context.Context) { return // don't reply default: - publicErr := "400 Bad Request" - if v, ok := err.(badRequestError); ok { - publicErr = publicErr + ": " + string(v) + if v, ok := err.(statusError); ok { + fmt.Fprintf(c.rwc, "HTTP/1.1 %d %s: %s%s%d %s: %s", v.code, StatusText(v.code), v.text, errorHeaders, v.code, StatusText(v.code), v.text) + return } - + publicErr := "400 Bad Request" fmt.Fprintf(c.rwc, "HTTP/1.1 "+publicErr+errorHeaders+publicErr) return }