mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +00:00
Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
8a4c24f9bb | ||
|
3de5aca7d0 | ||
|
8336dfde70 | ||
|
6b60550504 | ||
|
468fad45a2 | ||
|
e06b6fc58d | ||
|
b3799ba634 | ||
|
16afa6a740 | ||
|
817d7bdc0a | ||
|
14bb1e11b9 | ||
|
2297c34cdf | ||
|
26682773ca |
@ -1 +1,2 @@
|
|||||||
branch: master
|
branch: release-branch.go1.24
|
||||||
|
parent-branch: master
|
||||||
|
@ -12,7 +12,6 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
@ -73,7 +72,12 @@ func runGoAuth(client *http.Client, res *http.Response, url string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
base.Fatalf("go: could not parse netrc (GOAUTH=%s): %v", cfg.GOAUTH, err)
|
base.Fatalf("go: could not parse netrc (GOAUTH=%s): %v", cfg.GOAUTH, err)
|
||||||
}
|
}
|
||||||
for _, l := range lines {
|
// Process lines in reverse so that if the same machine is listed
|
||||||
|
// multiple times, we end up saving the earlier one
|
||||||
|
// (overwriting later ones). This matches the way the go command
|
||||||
|
// worked before GOAUTH.
|
||||||
|
for i := len(lines) - 1; i >= 0; i-- {
|
||||||
|
l := lines[i]
|
||||||
r := http.Request{Header: make(http.Header)}
|
r := http.Request{Header: make(http.Header)}
|
||||||
r.SetBasicAuth(l.login, l.password)
|
r.SetBasicAuth(l.login, l.password)
|
||||||
storeCredential(l.machine, r.Header)
|
storeCredential(l.machine, r.Header)
|
||||||
@ -137,11 +141,13 @@ func runGoAuth(client *http.Client, res *http.Response, url string) {
|
|||||||
func loadCredential(req *http.Request, url string) bool {
|
func loadCredential(req *http.Request, url string) bool {
|
||||||
currentPrefix := strings.TrimPrefix(url, "https://")
|
currentPrefix := strings.TrimPrefix(url, "https://")
|
||||||
// Iteratively try prefixes, moving up the path hierarchy.
|
// Iteratively try prefixes, moving up the path hierarchy.
|
||||||
for currentPrefix != "/" && currentPrefix != "." && currentPrefix != "" {
|
for {
|
||||||
headers, ok := credentialCache.Load(currentPrefix)
|
headers, ok := credentialCache.Load(currentPrefix)
|
||||||
if !ok {
|
if !ok {
|
||||||
// Move to the parent directory.
|
currentPrefix, _, ok = strings.Cut(currentPrefix, "/")
|
||||||
currentPrefix = path.Dir(currentPrefix)
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for key, values := range headers.(http.Header) {
|
for key, values := range headers.(http.Header) {
|
||||||
@ -151,7 +157,6 @@ func loadCredential(req *http.Request, url string) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// storeCredential caches or removes credentials (represented by HTTP headers)
|
// storeCredential caches or removes credentials (represented by HTTP headers)
|
||||||
|
@ -25,7 +25,29 @@ func TestCredentialCache(t *testing.T) {
|
|||||||
got := &http.Request{Header: make(http.Header)}
|
got := &http.Request{Header: make(http.Header)}
|
||||||
ok := loadCredential(got, tc.machine)
|
ok := loadCredential(got, tc.machine)
|
||||||
if !ok || !reflect.DeepEqual(got.Header, want.Header) {
|
if !ok || !reflect.DeepEqual(got.Header, want.Header) {
|
||||||
t.Errorf("loadCredential:\nhave %q\nwant %q", got.Header, want.Header)
|
t.Errorf("loadCredential(%q):\nhave %q\nwant %q", tc.machine, got.Header, want.Header)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Having stored those credentials, we should be able to look up longer URLs too.
|
||||||
|
extraCases := []netrcLine{
|
||||||
|
{"https://api.github.com/foo", "user", "pwd"},
|
||||||
|
{"https://api.github.com/foo/bar/baz", "user", "pwd"},
|
||||||
|
{"https://example.com/abc", "", ""},
|
||||||
|
{"https://example.com/?/../api.github.com/", "", ""},
|
||||||
|
{"https://example.com/?/../api.github.com", "", ""},
|
||||||
|
{"https://example.com/../api.github.com/", "", ""},
|
||||||
|
{"https://example.com/../api.github.com", "", ""},
|
||||||
|
}
|
||||||
|
for _, tc := range extraCases {
|
||||||
|
want := http.Request{Header: make(http.Header)}
|
||||||
|
if tc.login != "" {
|
||||||
|
want.SetBasicAuth(tc.login, tc.password)
|
||||||
|
}
|
||||||
|
got := &http.Request{Header: make(http.Header)}
|
||||||
|
loadCredential(got, tc.machine)
|
||||||
|
if !reflect.DeepEqual(got.Header, want.Header) {
|
||||||
|
t.Errorf("loadCredential(%q):\nhave %q\nwant %q", tc.machine, got.Header, want.Header)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
src/cmd/go/testdata/script/goauth_netrc.txt
vendored
7
src/cmd/go/testdata/script/goauth_netrc.txt
vendored
@ -2,8 +2,6 @@
|
|||||||
# credentials passed in HTTPS requests to VCS servers.
|
# credentials passed in HTTPS requests to VCS servers.
|
||||||
# See golang.org/issue/26232
|
# See golang.org/issue/26232
|
||||||
|
|
||||||
[short] skip
|
|
||||||
|
|
||||||
env GOPROXY=direct
|
env GOPROXY=direct
|
||||||
env GOSUMDB=off
|
env GOSUMDB=off
|
||||||
|
|
||||||
@ -55,7 +53,6 @@ go get vcs-test.golang.org/auth/or401
|
|||||||
env NETRC=$WORK/missing
|
env NETRC=$WORK/missing
|
||||||
! go get vcs-test.golang.org/auth/or401
|
! go get vcs-test.golang.org/auth/or401
|
||||||
stderr '^\tserver response: ACCESS DENIED, buddy$'
|
stderr '^\tserver response: ACCESS DENIED, buddy$'
|
||||||
|
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
module private.example.com
|
module private.example.com
|
||||||
-- $WORK/empty --
|
-- $WORK/empty --
|
||||||
@ -63,3 +60,7 @@ module private.example.com
|
|||||||
machine vcs-test.golang.org
|
machine vcs-test.golang.org
|
||||||
login aladdin
|
login aladdin
|
||||||
password opensesame
|
password opensesame
|
||||||
|
# first one should override this one
|
||||||
|
machine vcs-test.golang.org
|
||||||
|
login aladdin
|
||||||
|
password ignored
|
||||||
|
@ -1607,6 +1607,23 @@ var nameConstraintsTests = []nameConstraintsTest{
|
|||||||
leaf: leafSpec{sans: []string{"dns:.example.com"}},
|
leaf: leafSpec{sans: []string{"dns:.example.com"}},
|
||||||
expectedError: "cannot parse dnsName \".example.com\"",
|
expectedError: "cannot parse dnsName \".example.com\"",
|
||||||
},
|
},
|
||||||
|
// #86: URIs with IPv6 addresses with zones and ports are rejected
|
||||||
|
{
|
||||||
|
roots: []constraintsSpec{
|
||||||
|
{
|
||||||
|
ok: []string{"uri:example.com"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
intermediates: [][]constraintsSpec{
|
||||||
|
{
|
||||||
|
{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
leaf: leafSpec{
|
||||||
|
sans: []string{"uri:http://[2006:abcd::1%25.example.com]:16/"},
|
||||||
|
},
|
||||||
|
expectedError: "URI with IP",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) {
|
func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) {
|
||||||
|
@ -72,7 +72,9 @@ func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 ||
|
if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 ||
|
||||||
priv.Dp.Sign() <= 0 || priv.Dq.Sign() <= 0 || priv.Qinv.Sign() <= 0 {
|
priv.Dp != nil && priv.Dp.Sign() <= 0 ||
|
||||||
|
priv.Dq != nil && priv.Dq.Sign() <= 0 ||
|
||||||
|
priv.Qinv != nil && priv.Qinv.Sign() <= 0 {
|
||||||
return nil, errors.New("x509: private key contains zero or negative value")
|
return nil, errors.New("x509: private key contains zero or negative value")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"iter"
|
"iter"
|
||||||
"maps"
|
"maps"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -465,8 +466,10 @@ func matchURIConstraint(uri *url.URL, constraint string) (bool, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") ||
|
// netip.ParseAddr will reject the URI IPv6 literal form "[...]", so we
|
||||||
net.ParseIP(host) != nil {
|
// check if _either_ the string parses as an IP, or if it is enclosed in
|
||||||
|
// square brackets.
|
||||||
|
if _, err := netip.ParseAddr(host); err == nil || (strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]")) {
|
||||||
return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String())
|
return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,32 @@ func TestParsePKCS1PrivateKey(t *testing.T) {
|
|||||||
if _, err := ParsePKCS1PrivateKey(data); err == nil {
|
if _, err := ParsePKCS1PrivateKey(data); err == nil {
|
||||||
t.Errorf("parsing invalid private key did not result in an error")
|
t.Errorf("parsing invalid private key did not result in an error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A partial key without CRT values should still parse.
|
||||||
|
b, _ := asn1.Marshal(struct {
|
||||||
|
Version int
|
||||||
|
N *big.Int
|
||||||
|
E int
|
||||||
|
D *big.Int
|
||||||
|
P *big.Int
|
||||||
|
Q *big.Int
|
||||||
|
}{
|
||||||
|
N: priv.N,
|
||||||
|
E: priv.PublicKey.E,
|
||||||
|
D: priv.D,
|
||||||
|
P: priv.Primes[0],
|
||||||
|
Q: priv.Primes[1],
|
||||||
|
})
|
||||||
|
p2, err := ParsePKCS1PrivateKey(b)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("parsing partial private key resulted in an error: %v", err)
|
||||||
|
}
|
||||||
|
if !p2.Equal(priv) {
|
||||||
|
t.Errorf("partial private key did not match original key")
|
||||||
|
}
|
||||||
|
if p2.Precomputed.Dp == nil || p2.Precomputed.Dq == nil || p2.Precomputed.Qinv == nil {
|
||||||
|
t.Errorf("precomputed values not recomputed")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPKCS1MismatchPublicKeyFormat(t *testing.T) {
|
func TestPKCS1MismatchPublicKeyFormat(t *testing.T) {
|
||||||
|
@ -610,8 +610,9 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) {
|
|||||||
reqBodyClosed = false // have we closed the current req.Body?
|
reqBodyClosed = false // have we closed the current req.Body?
|
||||||
|
|
||||||
// Redirect behavior:
|
// Redirect behavior:
|
||||||
redirectMethod string
|
redirectMethod string
|
||||||
includeBody = true
|
includeBody = true
|
||||||
|
stripSensitiveHeaders = false
|
||||||
)
|
)
|
||||||
uerr := func(err error) error {
|
uerr := func(err error) error {
|
||||||
// the body may have been closed already by c.send()
|
// the body may have been closed already by c.send()
|
||||||
@ -678,7 +679,12 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) {
|
|||||||
// in case the user set Referer on their first request.
|
// in case the user set Referer on their first request.
|
||||||
// If they really want to override, they can do it in
|
// If they really want to override, they can do it in
|
||||||
// their CheckRedirect func.
|
// their CheckRedirect func.
|
||||||
copyHeaders(req)
|
if !stripSensitiveHeaders && reqs[0].URL.Host != req.URL.Host {
|
||||||
|
if !shouldCopyHeaderOnRedirect(reqs[0].URL, req.URL) {
|
||||||
|
stripSensitiveHeaders = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
copyHeaders(req, stripSensitiveHeaders)
|
||||||
|
|
||||||
// Add the Referer header from the most recent
|
// Add the Referer header from the most recent
|
||||||
// request URL to the new one, if it's not https->http:
|
// request URL to the new one, if it's not https->http:
|
||||||
@ -746,7 +752,7 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) {
|
|||||||
// makeHeadersCopier makes a function that copies headers from the
|
// makeHeadersCopier makes a function that copies headers from the
|
||||||
// initial Request, ireq. For every redirect, this function must be called
|
// initial Request, ireq. For every redirect, this function must be called
|
||||||
// so that it can copy headers into the upcoming Request.
|
// so that it can copy headers into the upcoming Request.
|
||||||
func (c *Client) makeHeadersCopier(ireq *Request) func(*Request) {
|
func (c *Client) makeHeadersCopier(ireq *Request) func(req *Request, stripSensitiveHeaders bool) {
|
||||||
// The headers to copy are from the very initial request.
|
// The headers to copy are from the very initial request.
|
||||||
// We use a closured callback to keep a reference to these original headers.
|
// We use a closured callback to keep a reference to these original headers.
|
||||||
var (
|
var (
|
||||||
@ -760,8 +766,7 @@ func (c *Client) makeHeadersCopier(ireq *Request) func(*Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
preq := ireq // The previous request
|
return func(req *Request, stripSensitiveHeaders bool) {
|
||||||
return func(req *Request) {
|
|
||||||
// If Jar is present and there was some initial cookies provided
|
// If Jar is present and there was some initial cookies provided
|
||||||
// via the request header, then we may need to alter the initial
|
// via the request header, then we may need to alter the initial
|
||||||
// cookies as we follow redirects since each redirect may end up
|
// cookies as we follow redirects since each redirect may end up
|
||||||
@ -798,12 +803,15 @@ func (c *Client) makeHeadersCopier(ireq *Request) func(*Request) {
|
|||||||
// Copy the initial request's Header values
|
// Copy the initial request's Header values
|
||||||
// (at least the safe ones).
|
// (at least the safe ones).
|
||||||
for k, vv := range ireqhdr {
|
for k, vv := range ireqhdr {
|
||||||
if shouldCopyHeaderOnRedirect(k, preq.URL, req.URL) {
|
sensitive := false
|
||||||
|
switch CanonicalHeaderKey(k) {
|
||||||
|
case "Authorization", "Www-Authenticate", "Cookie", "Cookie2":
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
if !(sensitive && stripSensitiveHeaders) {
|
||||||
req.Header[k] = vv
|
req.Header[k] = vv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
preq = req // Update previous Request with the current request
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -979,28 +987,23 @@ func (b *cancelTimerBody) Close() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldCopyHeaderOnRedirect(headerKey string, initial, dest *url.URL) bool {
|
func shouldCopyHeaderOnRedirect(initial, dest *url.URL) bool {
|
||||||
switch CanonicalHeaderKey(headerKey) {
|
// Permit sending auth/cookie headers from "foo.com"
|
||||||
case "Authorization", "Www-Authenticate", "Cookie", "Cookie2":
|
// to "sub.foo.com".
|
||||||
// Permit sending auth/cookie headers from "foo.com"
|
|
||||||
// to "sub.foo.com".
|
|
||||||
|
|
||||||
// Note that we don't send all cookies to subdomains
|
// Note that we don't send all cookies to subdomains
|
||||||
// automatically. This function is only used for
|
// automatically. This function is only used for
|
||||||
// Cookies set explicitly on the initial outgoing
|
// Cookies set explicitly on the initial outgoing
|
||||||
// client request. Cookies automatically added via the
|
// client request. Cookies automatically added via the
|
||||||
// CookieJar mechanism continue to follow each
|
// CookieJar mechanism continue to follow each
|
||||||
// cookie's scope as set by Set-Cookie. But for
|
// cookie's scope as set by Set-Cookie. But for
|
||||||
// outgoing requests with the Cookie header set
|
// outgoing requests with the Cookie header set
|
||||||
// directly, we don't know their scope, so we assume
|
// directly, we don't know their scope, so we assume
|
||||||
// it's for *.domain.com.
|
// it's for *.domain.com.
|
||||||
|
|
||||||
ihost := idnaASCIIFromURL(initial)
|
ihost := idnaASCIIFromURL(initial)
|
||||||
dhost := idnaASCIIFromURL(dest)
|
dhost := idnaASCIIFromURL(dest)
|
||||||
return isDomainOrSubdomain(dhost, ihost)
|
return isDomainOrSubdomain(dhost, ihost)
|
||||||
}
|
|
||||||
// All other headers are copied:
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// isDomainOrSubdomain reports whether sub is a subdomain (or exact
|
// isDomainOrSubdomain reports whether sub is a subdomain (or exact
|
||||||
|
@ -1536,6 +1536,55 @@ func testClientCopyHeadersOnRedirect(t *testing.T, mode testMode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #70530: Once we strip a header on a redirect to a different host,
|
||||||
|
// the header should stay stripped across any further redirects.
|
||||||
|
func TestClientStripHeadersOnRepeatedRedirect(t *testing.T) {
|
||||||
|
run(t, testClientStripHeadersOnRepeatedRedirect)
|
||||||
|
}
|
||||||
|
func testClientStripHeadersOnRepeatedRedirect(t *testing.T, mode testMode) {
|
||||||
|
var proto string
|
||||||
|
ts := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
|
||||||
|
if r.Host+r.URL.Path != "a.example.com/" {
|
||||||
|
if h := r.Header.Get("Authorization"); h != "" {
|
||||||
|
t.Errorf("on request to %v%v, Authorization=%q, want no header", r.Host, r.URL.Path, h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Follow a chain of redirects from a to b and back to a.
|
||||||
|
// The Authorization header is stripped on the first redirect to b,
|
||||||
|
// and stays stripped even if we're sent back to a.
|
||||||
|
switch r.Host + r.URL.Path {
|
||||||
|
case "a.example.com/":
|
||||||
|
Redirect(w, r, proto+"://b.example.com/", StatusFound)
|
||||||
|
case "b.example.com/":
|
||||||
|
Redirect(w, r, proto+"://b.example.com/redirect", StatusFound)
|
||||||
|
case "b.example.com/redirect":
|
||||||
|
Redirect(w, r, proto+"://a.example.com/redirect", StatusFound)
|
||||||
|
case "a.example.com/redirect":
|
||||||
|
w.Header().Set("X-Done", "true")
|
||||||
|
default:
|
||||||
|
t.Errorf("unexpected request to %v", r.URL)
|
||||||
|
}
|
||||||
|
})).ts
|
||||||
|
proto, _, _ = strings.Cut(ts.URL, ":")
|
||||||
|
|
||||||
|
c := ts.Client()
|
||||||
|
c.Transport.(*Transport).Dial = func(_ string, _ string) (net.Conn, error) {
|
||||||
|
return net.Dial("tcp", ts.Listener.Addr().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
req, _ := NewRequest("GET", proto+"://a.example.com/", nil)
|
||||||
|
req.Header.Add("Cookie", "foo=bar")
|
||||||
|
req.Header.Add("Authorization", "secretpassword")
|
||||||
|
res, err := c.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
if res.Header.Get("X-Done") != "true" {
|
||||||
|
t.Fatalf("response missing expected header: X-Done=true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Issue 22233: copy host when Client follows a relative redirect.
|
// Issue 22233: copy host when Client follows a relative redirect.
|
||||||
func TestClientCopyHostOnRedirect(t *testing.T) { run(t, testClientCopyHostOnRedirect) }
|
func TestClientCopyHostOnRedirect(t *testing.T) { run(t, testClientCopyHostOnRedirect) }
|
||||||
func testClientCopyHostOnRedirect(t *testing.T, mode testMode) {
|
func testClientCopyHostOnRedirect(t *testing.T, mode testMode) {
|
||||||
@ -1702,43 +1751,39 @@ func testClientAltersCookiesOnRedirect(t *testing.T, mode testMode) {
|
|||||||
// Part of Issue 4800
|
// Part of Issue 4800
|
||||||
func TestShouldCopyHeaderOnRedirect(t *testing.T) {
|
func TestShouldCopyHeaderOnRedirect(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
header string
|
|
||||||
initialURL string
|
initialURL string
|
||||||
destURL string
|
destURL string
|
||||||
want bool
|
want bool
|
||||||
}{
|
}{
|
||||||
{"User-Agent", "http://foo.com/", "http://bar.com/", true},
|
|
||||||
{"X-Foo", "http://foo.com/", "http://bar.com/", true},
|
|
||||||
|
|
||||||
// Sensitive headers:
|
// Sensitive headers:
|
||||||
{"cookie", "http://foo.com/", "http://bar.com/", false},
|
{"http://foo.com/", "http://bar.com/", false},
|
||||||
{"cookie2", "http://foo.com/", "http://bar.com/", false},
|
{"http://foo.com/", "http://bar.com/", false},
|
||||||
{"authorization", "http://foo.com/", "http://bar.com/", false},
|
{"http://foo.com/", "http://bar.com/", false},
|
||||||
{"authorization", "http://foo.com/", "https://foo.com/", true},
|
{"http://foo.com/", "https://foo.com/", true},
|
||||||
{"authorization", "http://foo.com:1234/", "http://foo.com:4321/", true},
|
{"http://foo.com:1234/", "http://foo.com:4321/", true},
|
||||||
{"www-authenticate", "http://foo.com/", "http://bar.com/", false},
|
{"http://foo.com/", "http://bar.com/", false},
|
||||||
{"authorization", "http://foo.com/", "http://[::1%25.foo.com]/", false},
|
{"http://foo.com/", "http://[::1%25.foo.com]/", false},
|
||||||
|
|
||||||
// But subdomains should work:
|
// But subdomains should work:
|
||||||
{"www-authenticate", "http://foo.com/", "http://foo.com/", true},
|
{"http://foo.com/", "http://foo.com/", true},
|
||||||
{"www-authenticate", "http://foo.com/", "http://sub.foo.com/", true},
|
{"http://foo.com/", "http://sub.foo.com/", true},
|
||||||
{"www-authenticate", "http://foo.com/", "http://notfoo.com/", false},
|
{"http://foo.com/", "http://notfoo.com/", false},
|
||||||
{"www-authenticate", "http://foo.com/", "https://foo.com/", true},
|
{"http://foo.com/", "https://foo.com/", true},
|
||||||
{"www-authenticate", "http://foo.com:80/", "http://foo.com/", true},
|
{"http://foo.com:80/", "http://foo.com/", true},
|
||||||
{"www-authenticate", "http://foo.com:80/", "http://sub.foo.com/", true},
|
{"http://foo.com:80/", "http://sub.foo.com/", true},
|
||||||
{"www-authenticate", "http://foo.com:443/", "https://foo.com/", true},
|
{"http://foo.com:443/", "https://foo.com/", true},
|
||||||
{"www-authenticate", "http://foo.com:443/", "https://sub.foo.com/", true},
|
{"http://foo.com:443/", "https://sub.foo.com/", true},
|
||||||
{"www-authenticate", "http://foo.com:1234/", "http://foo.com/", true},
|
{"http://foo.com:1234/", "http://foo.com/", true},
|
||||||
|
|
||||||
{"authorization", "http://foo.com/", "http://foo.com/", true},
|
{"http://foo.com/", "http://foo.com/", true},
|
||||||
{"authorization", "http://foo.com/", "http://sub.foo.com/", true},
|
{"http://foo.com/", "http://sub.foo.com/", true},
|
||||||
{"authorization", "http://foo.com/", "http://notfoo.com/", false},
|
{"http://foo.com/", "http://notfoo.com/", false},
|
||||||
{"authorization", "http://foo.com/", "https://foo.com/", true},
|
{"http://foo.com/", "https://foo.com/", true},
|
||||||
{"authorization", "http://foo.com:80/", "http://foo.com/", true},
|
{"http://foo.com:80/", "http://foo.com/", true},
|
||||||
{"authorization", "http://foo.com:80/", "http://sub.foo.com/", true},
|
{"http://foo.com:80/", "http://sub.foo.com/", true},
|
||||||
{"authorization", "http://foo.com:443/", "https://foo.com/", true},
|
{"http://foo.com:443/", "https://foo.com/", true},
|
||||||
{"authorization", "http://foo.com:443/", "https://sub.foo.com/", true},
|
{"http://foo.com:443/", "https://sub.foo.com/", true},
|
||||||
{"authorization", "http://foo.com:1234/", "http://foo.com/", true},
|
{"http://foo.com:1234/", "http://foo.com/", true},
|
||||||
}
|
}
|
||||||
for i, tt := range tests {
|
for i, tt := range tests {
|
||||||
u0, err := url.Parse(tt.initialURL)
|
u0, err := url.Parse(tt.initialURL)
|
||||||
@ -1751,10 +1796,10 @@ func TestShouldCopyHeaderOnRedirect(t *testing.T) {
|
|||||||
t.Errorf("%d. dest URL %q parse error: %v", i, tt.destURL, err)
|
t.Errorf("%d. dest URL %q parse error: %v", i, tt.destURL, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
got := Export_shouldCopyHeaderOnRedirect(tt.header, u0, u1)
|
got := Export_shouldCopyHeaderOnRedirect(u0, u1)
|
||||||
if got != tt.want {
|
if got != tt.want {
|
||||||
t.Errorf("%d. shouldCopyHeaderOnRedirect(%q, %q => %q) = %v; want %v",
|
t.Errorf("%d. shouldCopyHeaderOnRedirect(%q => %q) = %v; want %v",
|
||||||
i, tt.header, tt.initialURL, tt.destURL, got, tt.want)
|
i, tt.initialURL, tt.destURL, got, tt.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,56 +10,56 @@ import "strings"
|
|||||||
// LocalhostCert is a PEM-encoded TLS cert with SAN IPs
|
// LocalhostCert is a PEM-encoded TLS cert with SAN IPs
|
||||||
// "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT.
|
// "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT.
|
||||||
// generated from src/crypto/tls:
|
// generated from src/crypto/tls:
|
||||||
// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
|
// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com,*.example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
|
||||||
var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
|
var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
|
||||||
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
|
||||||
WkBKOclmOV2xlTVuPw==
|
rF7r4gUnKeC7mYIH1zypY7laskopiLFAfe96Kg==
|
||||||
-----END CERTIFICATE-----`)
|
-----END CERTIFICATE-----`)
|
||||||
|
|
||||||
// LocalhostKey is the private key for LocalhostCert.
|
// LocalhostKey is the private key for LocalhostCert.
|
||||||
var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY-----
|
var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY-----
|
||||||
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
|
||||||
ZboOWVe3icTy64BT3OQhmg==
|
jel6uj2FOP9g54s+GzlSVg/T
|
||||||
-----END RSA TESTING KEY-----`))
|
-----END RSA TESTING KEY-----`))
|
||||||
|
|
||||||
func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
|
func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user