// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// gitauth uses 'git credential' to implement the GOAUTH protocol described in
// https://golang.org/issue/26232. It expects an absolute path to the working
// directory for the 'git' command as the first command-line argument.
//
// Example GOAUTH usage:
//
//	export GOAUTH="gitauth $HOME"
//
// See https://git-scm.com/docs/gitcredentials or run 'man gitcredentials' for
// information on how to configure 'git credential'.
package main

import (
	"bytes"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

func main() {
	if len(os.Args) < 2 || !filepath.IsAbs(os.Args[1]) {
		fmt.Fprintf(os.Stderr, "usage: %s WORKDIR [URL]", os.Args[0])
		os.Exit(2)
	}

	log.SetPrefix("gitauth: ")

	if len(os.Args) != 3 {
		// No explicit URL was passed on the command line, but 'git credential'
		// provides no way to enumerate existing credentials.
		// Wait for a request for a specific URL.
		return
	}

	u, err := url.ParseRequestURI(os.Args[2])
	if err != nil {
		log.Fatalf("invalid request URI (%v): %q\n", err, os.Args[1])
	}

	var (
		prefix     *url.URL
		lastHeader http.Header
		lastStatus = http.StatusUnauthorized
	)
	for lastStatus == http.StatusUnauthorized {
		cmd := exec.Command("git", "credential", "fill")

		// We don't want to execute a 'git' command in an arbitrary directory, since
		// that opens up a number of config-injection attacks (for example,
		// https://golang.org/issue/29230). Instead, we have the user configure a
		// directory explicitly on the command line.
		cmd.Dir = os.Args[1]

		cmd.Stdin = strings.NewReader(fmt.Sprintf("url=%s\n", u))
		cmd.Stderr = os.Stderr
		out, err := cmd.Output()
		if err != nil {
			log.Fatalf("'git credential fill' failed: %v\n", err)
		}

		prefix = new(url.URL)
		var username, password string
		lines := strings.Split(string(out), "\n")
		for _, line := range lines {
			frags := strings.SplitN(line, "=", 2)
			if len(frags) != 2 {
				continue // Ignore unrecognized response lines.
			}
			switch strings.TrimSpace(frags[0]) {
			case "protocol":
				prefix.Scheme = frags[1]
			case "host":
				prefix.Host = frags[1]
			case "path":
				prefix.Path = frags[1]
			case "username":
				username = frags[1]
			case "password":
				password = frags[1]
			case "url":
				// Write to a local variable instead of updating prefix directly:
				// if the url field is malformed, we don't want to invalidate
				// information parsed from the protocol, host, and path fields.
				u, err := url.ParseRequestURI(frags[1])
				if err == nil {
					prefix = u
				} else {
					log.Printf("malformed URL from 'git credential fill' (%v): %q\n", err, frags[1])
					// Proceed anyway: we might be able to parse the prefix from other fields of the response.
				}
			}
		}

		// Double-check that the URL Git gave us is a prefix of the one we requested.
		if !strings.HasPrefix(u.String(), prefix.String()) {
			log.Fatalf("requested a credential for %q, but 'git credential fill' provided one for %q\n", u, prefix)
		}

		// Send a HEAD request to try to detect whether the credential is valid.
		// If the user just typed in a correct password and has caching enabled,
		// we don't want to nag them for it again the next time they run a 'go' command.
		req, err := http.NewRequest("HEAD", u.String(), nil)
		if err != nil {
			log.Fatalf("internal error constructing HTTP HEAD request: %v\n", err)
		}
		req.SetBasicAuth(username, password)
		lastHeader = req.Header
		resp, err := http.DefaultClient.Do(req)
		if err != nil {
			log.Printf("HTTPS HEAD request failed to connect: %v\n", err)
			// Couldn't verify the credential, but we have no evidence that it is invalid either.
			// Proceed, but don't update git's credential cache.
			break
		}
		lastStatus = resp.StatusCode

		if resp.StatusCode != http.StatusOK {
			log.Printf("%s: %v %s\n", u, resp.StatusCode, http.StatusText(resp.StatusCode))
		}

		if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusUnauthorized {
			// We learned something about the credential: it either worked or it was invalid.
			// Approve or reject the credential (on a best-effort basis)
			// so that the git credential helper can update its cache as appropriate.
			action := "approve"
			if resp.StatusCode != http.StatusOK {
				action = "reject"
			}
			cmd = exec.Command("git", "credential", action)
			cmd.Stderr = os.Stderr
			cmd.Stdout = os.Stderr
			cmd.Stdin = bytes.NewReader(out)
			_ = cmd.Run()
		}
	}

	// Write out the credential in the format expected by the 'go' command.
	fmt.Printf("%s\n\n", prefix)
	lastHeader.Write(os.Stdout)
	fmt.Println()
}
