mirror of
https://github.com/golang/go
synced 2024-11-24 07:40:17 -07:00
cmd/go/internal/web2: make netrc parsing more robust
- Respect the NETRC environment variable if set. - Ignore lines that contain macro definitions. - Associate the 'machine' token with only the tokens that follow (not precede) it. Updates #29888 Updates #26232 Change-Id: I3128b7d6da2d6492df7c864e165eea1a27384f0f Reviewed-on: https://go-review.googlesource.com/c/go/+/161698 Run-TryBot: Bryan C. Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Jay Conrod <jayconrod@google.com>
This commit is contained in:
parent
131eb8fbf8
commit
2d68380713
@ -37,29 +37,61 @@ type netrcLine struct {
|
||||
password string
|
||||
}
|
||||
|
||||
var netrcOnce sync.Once
|
||||
var netrc []netrcLine
|
||||
var (
|
||||
netrcOnce sync.Once
|
||||
netrc []netrcLine
|
||||
netrcErr error
|
||||
)
|
||||
|
||||
func parseNetrc(data string) []netrcLine {
|
||||
// See https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html
|
||||
// for documentation on the .netrc format.
|
||||
var nrc []netrcLine
|
||||
var l netrcLine
|
||||
inMacro := false
|
||||
for _, line := range strings.Split(data, "\n") {
|
||||
if inMacro {
|
||||
if line == "" {
|
||||
inMacro = false
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
f := strings.Fields(line)
|
||||
for i := 0; i < len(f)-1; i += 2 {
|
||||
i := 0
|
||||
for ; i < len(f)-1; i += 2 {
|
||||
// Reset at each "machine" token.
|
||||
// “The auto-login process searches the .netrc file for a machine token
|
||||
// that matches […]. Once a match is made, the subsequent .netrc tokens
|
||||
// are processed, stopping when the end of file is reached or another
|
||||
// machine or a default token is encountered.”
|
||||
switch f[i] {
|
||||
case "machine":
|
||||
l.machine = f[i+1]
|
||||
l = netrcLine{machine: f[i+1]}
|
||||
case "default":
|
||||
break
|
||||
case "login":
|
||||
l.login = f[i+1]
|
||||
case "password":
|
||||
l.password = f[i+1]
|
||||
case "macdef":
|
||||
// “A macro is defined with the specified name; its contents begin with
|
||||
// the next .netrc line and continue until a null line (consecutive
|
||||
// new-line characters) is encountered.”
|
||||
inMacro = true
|
||||
}
|
||||
if l.machine != "" && l.login != "" && l.password != "" {
|
||||
nrc = append(nrc, l)
|
||||
l = netrcLine{}
|
||||
}
|
||||
}
|
||||
if l.machine != "" && l.login != "" && l.password != "" {
|
||||
nrc = append(nrc, l)
|
||||
l = netrcLine{}
|
||||
|
||||
if i < len(f) && f[i] == "default" {
|
||||
// “There can be only one default token, and it must be after all machine tokens.”
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nrc
|
||||
}
|
||||
|
||||
@ -73,22 +105,36 @@ func havePassword(machine string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func netrcPath() string {
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
return filepath.Join(os.Getenv("USERPROFILE"), "_netrc")
|
||||
case "plan9":
|
||||
return filepath.Join(os.Getenv("home"), ".netrc")
|
||||
default:
|
||||
return filepath.Join(os.Getenv("HOME"), ".netrc")
|
||||
func netrcPath() (string, error) {
|
||||
if env := os.Getenv("NETRC"); env != "" {
|
||||
return env, nil
|
||||
}
|
||||
dir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
base := ".netrc"
|
||||
if runtime.GOOS == "windows" {
|
||||
base = "_netrc"
|
||||
}
|
||||
return filepath.Join(dir, base), nil
|
||||
}
|
||||
|
||||
func readNetrc() {
|
||||
data, err := ioutil.ReadFile(netrcPath())
|
||||
path, err := netrcPath()
|
||||
if err != nil {
|
||||
netrcErr = err
|
||||
return
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
netrcErr = err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
netrc = parseNetrc(string(data))
|
||||
}
|
||||
|
||||
|
@ -10,16 +10,37 @@ import (
|
||||
)
|
||||
|
||||
var testNetrc = `
|
||||
machine incomplete
|
||||
password none
|
||||
|
||||
machine api.github.com
|
||||
login user
|
||||
password pwd
|
||||
|
||||
machine incomlete.host
|
||||
login justlogin
|
||||
|
||||
|
||||
machine test.host
|
||||
login user2
|
||||
password pwd2
|
||||
|
||||
machine oneline login user3 password pwd3
|
||||
|
||||
machine ignore.host macdef ignore
|
||||
login nobody
|
||||
password nothing
|
||||
|
||||
machine hasmacro.too macdef ignore-next-lines login user4 password pwd4
|
||||
login nobody
|
||||
password nothing
|
||||
|
||||
default
|
||||
login anonymous
|
||||
password gopher@golang.org
|
||||
|
||||
machine after.default
|
||||
login oops
|
||||
password too-late-in-file
|
||||
`
|
||||
|
||||
func TestReadNetrc(t *testing.T) {
|
||||
@ -27,6 +48,8 @@ func TestReadNetrc(t *testing.T) {
|
||||
want := []netrcLine{
|
||||
{"api.github.com", "user", "pwd"},
|
||||
{"test.host", "user2", "pwd2"},
|
||||
{"oneline", "user3", "pwd3"},
|
||||
{"hasmacro.too", "user4", "pwd4"},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(lines, want) {
|
||||
|
Loading…
Reference in New Issue
Block a user