Skip to content

Commit 58de7c6

Browse files
Bryan C. Millsrsc
Bryan C. Mills
authored andcommitted
cmd/go/internal/web: merge internal/web2 into web
The cmd/go/internal/web package was forked in order to support direct HTTPS fetches from widely-used hosting providers,¹ but direct fetches were subsequently dropped in CL 107657. The forked web2 package, with its GitHub-specific diagnostics and .netrc support, remained in use for module proxy support, but was not used for the initial '?go-get=1' path resolution, so the .netrc file was only used to fetch from already-resolved module protocol servers. This CL moves the .netrc support into its own (new) package, cmd/go/internal/auth, and consolidates the web and web2 packages back into just web. As a result, fetches via the web package now support .netrc, and fetches that previously used web2 now enforce the same security policies as web (such as prohibiting HTTPS-to-HTTP redirects). ¹golang/vgo@63138cb Fixes #29591 Fixes #29888 Fixes #30610 Updates #26232 Change-Id: Ia3a13526e443679cf14a72a1f3db96f336ce5e73 Reviewed-on: https://go-review.googlesource.com/c/go/+/170879 Run-TryBot: Russ Cox <[email protected]> Reviewed-by: Russ Cox <[email protected]> Reviewed-by: Jay Conrod <[email protected]>
1 parent 807761f commit 58de7c6

20 files changed

+509
-879
lines changed

src/cmd/go/internal/auth/auth.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2019 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Package auth provides access to user-provided authentication credentials.
6+
package auth
7+
8+
import "net/http"
9+
10+
// AddCredentials fills in the user's credentials for req, if any.
11+
// The return value reports whether any matching credentials were found.
12+
func AddCredentials(req *http.Request) (added bool) {
13+
// TODO(golang.org/issue/26232): Support arbitrary user-provided credentials.
14+
netrcOnce.Do(readNetrc)
15+
for _, l := range netrc {
16+
if l.machine == req.URL.Host {
17+
req.SetBasicAuth(l.login, l.password)
18+
return true
19+
}
20+
}
21+
22+
return false
23+
}

src/cmd/go/internal/auth/netrc.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright 2019 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package auth
6+
7+
import (
8+
"io/ioutil"
9+
"os"
10+
"path/filepath"
11+
"runtime"
12+
"strings"
13+
"sync"
14+
)
15+
16+
type netrcLine struct {
17+
machine string
18+
login string
19+
password string
20+
}
21+
22+
var (
23+
netrcOnce sync.Once
24+
netrc []netrcLine
25+
netrcErr error
26+
)
27+
28+
func parseNetrc(data string) []netrcLine {
29+
// See https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html
30+
// for documentation on the .netrc format.
31+
var nrc []netrcLine
32+
var l netrcLine
33+
inMacro := false
34+
for _, line := range strings.Split(data, "\n") {
35+
if inMacro {
36+
if line == "" {
37+
inMacro = false
38+
}
39+
continue
40+
}
41+
42+
f := strings.Fields(line)
43+
i := 0
44+
for ; i < len(f)-1; i += 2 {
45+
// Reset at each "machine" token.
46+
// “The auto-login process searches the .netrc file for a machine token
47+
// that matches […]. Once a match is made, the subsequent .netrc tokens
48+
// are processed, stopping when the end of file is reached or another
49+
// machine or a default token is encountered.”
50+
switch f[i] {
51+
case "machine":
52+
l = netrcLine{machine: f[i+1]}
53+
case "default":
54+
break
55+
case "login":
56+
l.login = f[i+1]
57+
case "password":
58+
l.password = f[i+1]
59+
case "macdef":
60+
// “A macro is defined with the specified name; its contents begin with
61+
// the next .netrc line and continue until a null line (consecutive
62+
// new-line characters) is encountered.”
63+
inMacro = true
64+
}
65+
if l.machine != "" && l.login != "" && l.password != "" {
66+
nrc = append(nrc, l)
67+
l = netrcLine{}
68+
}
69+
}
70+
71+
if i < len(f) && f[i] == "default" {
72+
// “There can be only one default token, and it must be after all machine tokens.”
73+
break
74+
}
75+
}
76+
77+
return nrc
78+
}
79+
80+
func netrcPath() (string, error) {
81+
if env := os.Getenv("NETRC"); env != "" {
82+
return env, nil
83+
}
84+
dir, err := os.UserHomeDir()
85+
if err != nil {
86+
return "", err
87+
}
88+
base := ".netrc"
89+
if runtime.GOOS == "windows" {
90+
base = "_netrc"
91+
}
92+
return filepath.Join(dir, base), nil
93+
}
94+
95+
func readNetrc() {
96+
path, err := netrcPath()
97+
if err != nil {
98+
netrcErr = err
99+
return
100+
}
101+
102+
data, err := ioutil.ReadFile(path)
103+
if err != nil {
104+
if !os.IsNotExist(err) {
105+
netrcErr = err
106+
}
107+
return
108+
}
109+
110+
netrc = parseNetrc(string(data))
111+
}

src/cmd/go/internal/web2/web_test.go renamed to src/cmd/go/internal/auth/netrc_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
package web2
5+
package auth
66

77
import (
88
"reflect"
@@ -43,7 +43,7 @@ login oops
4343
password too-late-in-file
4444
`
4545

46-
func TestReadNetrc(t *testing.T) {
46+
func TestParseNetrc(t *testing.T) {
4747
lines := parseNetrc(testNetrc)
4848
want := []netrcLine{
4949
{"api.github.com", "user", "pwd"},

src/cmd/go/internal/bug/bug.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"fmt"
1111
"io"
1212
"io/ioutil"
13+
urlpkg "net/url"
1314
"os"
1415
"os/exec"
1516
"path/filepath"
@@ -62,7 +63,7 @@ func runBug(cmd *base.Command, args []string) {
6263
fmt.Fprintln(&buf, "```")
6364

6465
body := buf.String()
65-
url := "https://github.com/golang/go/issues/new?body=" + web.QueryEscape(body)
66+
url := "https://github.com/golang/go/issues/new?body=" + urlpkg.QueryEscape(body)
6667
if !web.OpenBrowser(url) {
6768
fmt.Print("Please file a new issue at golang.org/issue/new using this template:\n\n")
6869
fmt.Print(body)
@@ -130,7 +131,12 @@ func printCDetails(w io.Writer) {
130131
}
131132

132133
func inspectGoVersion(w io.Writer) {
133-
data, err := web.Get("https://golang.org/VERSION?m=text")
134+
data, err := web.GetBytes(&urlpkg.URL{
135+
Scheme: "https",
136+
Host: "golang.org",
137+
Path: "/VERSION",
138+
RawQuery: "?m=text",
139+
})
134140
if err != nil {
135141
if cfg.BuildV {
136142
fmt.Printf("failed to read from golang.org/VERSION: %v\n", err)

src/cmd/go/internal/get/get.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ func downloadPackage(p *load.Package) error {
392392
blindRepo bool // set if the repo has unusual configuration
393393
)
394394

395-
security := web.Secure
395+
security := web.SecureOnly
396396
if Insecure {
397397
security = web.Insecure
398398
}

0 commit comments

Comments
 (0)