From: Caleb Spare Date: Tue, 20 Oct 2015 07:35:42 +0000 (-0700) Subject: net/http: detect when an HTTPS client contacts an HTTP server X-Git-Tag: go1.6beta1~420 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=babdb3832072b6ca55e2dfe071bac25d865f8911;p=gostls13.git net/http: detect when an HTTPS client contacts an HTTP server Inspect the crypto/tls error to recognize this case and give a more helpful error. Fixes #11111. Change-Id: I63f6af8c375aa892326ccccbd29655d54d68df0b Reviewed-on: https://go-review.googlesource.com/16079 Run-TryBot: Caleb Spare TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- diff --git a/src/net/http/client.go b/src/net/http/client.go index 7f2fbb4678..47f145a0ca 100644 --- a/src/net/http/client.go +++ b/src/net/http/client.go @@ -10,6 +10,7 @@ package http import ( + "crypto/tls" "encoding/base64" "errors" "fmt" @@ -222,6 +223,14 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) { if resp != nil { log.Printf("RoundTripper returned a response & error; ignoring response") } + if tlsErr, ok := err.(tls.RecordHeaderError); ok { + // If we get a bad TLS record header, check to see if the + // response looks like HTTP and give a more helpful error. + // See golang.org/issue/11111. + if string(tlsErr.RecordHeader[:]) == "HTTP/" { + err = errors.New("http: server gave HTTP response to HTTPS client") + } + } return nil, err } return resp, nil diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go index 01f8cbaa2d..40d5109862 100644 --- a/src/net/http/client_test.go +++ b/src/net/http/client_test.go @@ -743,6 +743,20 @@ func TestResponseSetsTLSConnectionState(t *testing.T) { } } +// Check that an HTTPS client can interpret a particular TLS error +// to determine that the server is speaking HTTP. +// See golang.org/issue/11111. +func TestHTTPSClientDetectsHTTPServer(t *testing.T) { + defer afterTest(t) + ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {})) + defer ts.Close() + + _, err := Get(strings.Replace(ts.URL, "http", "https", 1)) + if got := err.Error(); !strings.Contains(got, "HTTP response to HTTPS client") { + t.Fatalf("error = %q; want error indicating HTTP response to HTTPS request", got) + } +} + // Verify Response.ContentLength is populated. https://golang.org/issue/4126 func TestClientHeadContentLength(t *testing.T) { defer afterTest(t)