...

Source file src/pkg/cmd/go/internal/auth/netrc.go

     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	}
   112	

View as plain text