]> Cypherpunks.ru repositories - gostls13.git/commitdiff
net/http: use ASCII space trimming throughout
authorFilippo Valsorda <filippo@golang.org>
Fri, 1 May 2020 05:14:04 +0000 (01:14 -0400)
committerFilippo Valsorda <filippo@golang.org>
Wed, 6 May 2020 16:25:52 +0000 (16:25 +0000)
Security hardening against HTTP request smuggling. Thank you to ZeddYu
for reporting this issue.

Change-Id: I98bd9f8ffe58360fc3bca9dc5d9a106773e55373
Reviewed-on: https://go-review.googlesource.com/c/go/+/231419
Reviewed-by: Katie Hockman <katie@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/net/http/cgi/host.go
src/net/http/cookie.go
src/net/http/fs.go
src/net/http/httptest/recorder.go
src/net/http/httputil/reverseproxy.go
src/net/http/transfer.go

index 215bb83a39f501b30f54c5e17ee34e6cfeff6e91..a038575480a4753ca627afd1c3e35ca9a016c7bd 100644 (file)
@@ -21,6 +21,7 @@ import (
        "log"
        "net"
        "net/http"
+       "net/textproto"
        "os"
        "os/exec"
        "path/filepath"
@@ -276,8 +277,8 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
                        continue
                }
                header, val := parts[0], parts[1]
-               header = strings.TrimSpace(header)
-               val = strings.TrimSpace(val)
+               header = textproto.TrimString(header)
+               val = textproto.TrimString(val)
                switch {
                case header == "Status":
                        if len(val) < 3 {
index 5c572d6dc5a775eb51ff78d36612d49294f3af5b..d7a8f5e94e56ea7557461100ec8c7e12b61d0fa7 100644 (file)
@@ -7,6 +7,7 @@ package http
 import (
        "log"
        "net"
+       "net/textproto"
        "strconv"
        "strings"
        "time"
@@ -60,11 +61,11 @@ func readSetCookies(h Header) []*Cookie {
        }
        cookies := make([]*Cookie, 0, cookieCount)
        for _, line := range h["Set-Cookie"] {
-               parts := strings.Split(strings.TrimSpace(line), ";")
+               parts := strings.Split(textproto.TrimString(line), ";")
                if len(parts) == 1 && parts[0] == "" {
                        continue
                }
-               parts[0] = strings.TrimSpace(parts[0])
+               parts[0] = textproto.TrimString(parts[0])
                j := strings.Index(parts[0], "=")
                if j < 0 {
                        continue
@@ -83,7 +84,7 @@ func readSetCookies(h Header) []*Cookie {
                        Raw:   line,
                }
                for i := 1; i < len(parts); i++ {
-                       parts[i] = strings.TrimSpace(parts[i])
+                       parts[i] = textproto.TrimString(parts[i])
                        if len(parts[i]) == 0 {
                                continue
                        }
@@ -242,7 +243,7 @@ func readCookies(h Header, filter string) []*Cookie {
 
        cookies := make([]*Cookie, 0, len(lines)+strings.Count(lines[0], ";"))
        for _, line := range lines {
-               line = strings.TrimSpace(line)
+               line = textproto.TrimString(line)
 
                var part string
                for len(line) > 0 { // continue since we have rest
@@ -251,7 +252,7 @@ func readCookies(h Header, filter string) []*Cookie {
                        } else {
                                part, line = line, ""
                        }
-                       part = strings.TrimSpace(part)
+                       part = textproto.TrimString(part)
                        if len(part) == 0 {
                                continue
                        }
index d2144857e84300a54ba347aaead4285e0f666c26..f95f2426b7d4ec63000f4073ce2e3cd2001b3189 100644 (file)
@@ -756,7 +756,7 @@ func parseRange(s string, size int64) ([]httpRange, error) {
        var ranges []httpRange
        noOverlap := false
        for _, ra := range strings.Split(s[len(b):], ",") {
-               ra = strings.TrimSpace(ra)
+               ra = textproto.TrimString(ra)
                if ra == "" {
                        continue
                }
@@ -764,7 +764,7 @@ func parseRange(s string, size int64) ([]httpRange, error) {
                if i < 0 {
                        return nil, errors.New("invalid range")
                }
-               start, end := strings.TrimSpace(ra[:i]), strings.TrimSpace(ra[i+1:])
+               start, end := textproto.TrimString(ra[:i]), textproto.TrimString(ra[i+1:])
                var r httpRange
                if start == "" {
                        // If no start is specified, end specifies the
index d0bc0fade98d91abe87e05d328b4414e49c707b7..13697454cb08f67c46bed9d918d7930f423b9d5f 100644 (file)
@@ -9,6 +9,7 @@ import (
        "fmt"
        "io/ioutil"
        "net/http"
+       "net/textproto"
        "strconv"
        "strings"
 
@@ -221,7 +222,7 @@ func (rw *ResponseRecorder) Result() *http.Response {
 // This a modified version of same function found in net/http/transfer.go. This
 // one just ignores an invalid header.
 func parseContentLength(cl string) int64 {
-       cl = strings.TrimSpace(cl)
+       cl = textproto.TrimString(cl)
        if cl == "" {
                return -1
        }
index 70de7b107db235f8f26fd7ecf528976daa292560..3f48fab544e912506e94f78b4eed8b23b5f31019 100644 (file)
@@ -13,6 +13,7 @@ import (
        "log"
        "net"
        "net/http"
+       "net/textproto"
        "net/url"
        "strings"
        "sync"
@@ -387,7 +388,7 @@ func shouldPanicOnCopyError(req *http.Request) bool {
 func removeConnectionHeaders(h http.Header) {
        for _, f := range h["Connection"] {
                for _, sf := range strings.Split(f, ",") {
-                       if sf = strings.TrimSpace(sf); sf != "" {
+                       if sf = textproto.TrimString(sf); sf != "" {
                                h.Del(sf)
                        }
                }
index 350403c3667bb6250d41b9238c9ac11466201d49..6d5ea05c32aa79eddd3e4210f6dfde491ef4bac1 100644 (file)
@@ -660,9 +660,9 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header,
                // Content-Length headers if they differ in value.
                // If there are dups of the value, remove the dups.
                // See Issue 16490.
-               first := strings.TrimSpace(contentLens[0])
+               first := textproto.TrimString(contentLens[0])
                for _, ct := range contentLens[1:] {
-                       if first != strings.TrimSpace(ct) {
+                       if first != textproto.TrimString(ct) {
                                return 0, fmt.Errorf("http: message cannot contain multiple Content-Length headers; got %q", contentLens)
                        }
                }
@@ -701,7 +701,7 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header,
        // Logic based on Content-Length
        var cl string
        if len(contentLens) == 1 {
-               cl = strings.TrimSpace(contentLens[0])
+               cl = textproto.TrimString(contentLens[0])
        }
        if cl != "" {
                n, err := parseContentLength(cl)
@@ -1032,7 +1032,7 @@ func (bl bodyLocked) Read(p []byte) (n int, err error) {
 // parseContentLength trims whitespace from s and returns -1 if no value
 // is set, or the value if it's >= 0.
 func parseContentLength(cl string) (int64, error) {
-       cl = strings.TrimSpace(cl)
+       cl = textproto.TrimString(cl)
        if cl == "" {
                return -1, nil
        }