golang.org/x/tools@v0.21.0/cmd/auth/netrcauth/netrcauth.go (about)

     1  // Copyright 2018 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  // netrcauth uses a .netrc file (or _netrc file on Windows) to implement the
     6  // GOAUTH protocol described in https://golang.org/issue/26232.
     7  // It expects the location of the file as the first command-line argument.
     8  //
     9  // Example GOAUTH usage:
    10  //
    11  //	export GOAUTH="netrcauth $HOME/.netrc"
    12  //
    13  // See https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html
    14  // or run 'man 5 netrc' for a description of the .netrc file format.
    15  package main
    16  
    17  import (
    18  	"fmt"
    19  	"log"
    20  	"net/http"
    21  	"net/url"
    22  	"os"
    23  	"strings"
    24  )
    25  
    26  func main() {
    27  	if len(os.Args) < 2 {
    28  		fmt.Fprintf(os.Stderr, "usage: %s NETRCFILE [URL]", os.Args[0])
    29  		os.Exit(2)
    30  	}
    31  
    32  	log.SetPrefix("netrcauth: ")
    33  
    34  	if len(os.Args) != 2 {
    35  		// An explicit URL was passed on the command line, but netrcauth does not
    36  		// have any URL-specific output: it dumps the entire .netrc file at the
    37  		// first call.
    38  		return
    39  	}
    40  
    41  	path := os.Args[1]
    42  
    43  	data, err := os.ReadFile(path)
    44  	if err != nil {
    45  		if os.IsNotExist(err) {
    46  			return
    47  		}
    48  		log.Fatalf("failed to read %s: %v\n", path, err)
    49  	}
    50  
    51  	u := &url.URL{Scheme: "https"}
    52  	lines := parseNetrc(string(data))
    53  	for _, l := range lines {
    54  		u.Host = l.machine
    55  		fmt.Printf("%s\n\n", u)
    56  
    57  		req := &http.Request{Header: make(http.Header)}
    58  		req.SetBasicAuth(l.login, l.password)
    59  		req.Header.Write(os.Stdout)
    60  		fmt.Println()
    61  	}
    62  }
    63  
    64  // The following functions were extracted from src/cmd/go/internal/web2/web.go
    65  // as of https://golang.org/cl/161698.
    66  
    67  type netrcLine struct {
    68  	machine  string
    69  	login    string
    70  	password string
    71  }
    72  
    73  func parseNetrc(data string) []netrcLine {
    74  	// See https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html
    75  	// for documentation on the .netrc format.
    76  	var nrc []netrcLine
    77  	var l netrcLine
    78  	inMacro := false
    79  	for _, line := range strings.Split(data, "\n") {
    80  		if inMacro {
    81  			if line == "" {
    82  				inMacro = false
    83  			}
    84  			continue
    85  		}
    86  
    87  		f := strings.Fields(line)
    88  		i := 0
    89  		for ; i < len(f)-1; i += 2 {
    90  			// Reset at each "machine" token.
    91  			// “The auto-login process searches the .netrc file for a machine token
    92  			// that matches […]. Once a match is made, the subsequent .netrc tokens
    93  			// are processed, stopping when the end of file is reached or another
    94  			// machine or a default token is encountered.”
    95  			switch f[i] {
    96  			case "machine":
    97  				l = netrcLine{machine: f[i+1]}
    98  			case "default":
    99  				break
   100  			case "login":
   101  				l.login = f[i+1]
   102  			case "password":
   103  				l.password = f[i+1]
   104  			case "macdef":
   105  				// “A macro is defined with the specified name; its contents begin with
   106  				// the next .netrc line and continue until a null line (consecutive
   107  				// new-line characters) is encountered.”
   108  				inMacro = true
   109  			}
   110  			if l.machine != "" && l.login != "" && l.password != "" {
   111  				nrc = append(nrc, l)
   112  				l = netrcLine{}
   113  			}
   114  		}
   115  
   116  		if i < len(f) && f[i] == "default" {
   117  			// “There can be only one default token, and it must be after all machine tokens.”
   118  			break
   119  		}
   120  	}
   121  
   122  	return nrc
   123  }