// Copyright 2013 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.

package main

import (
	"bytes"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"sync"
)

var debugDarwinRoots = true

// This code is only used when compiling without cgo.
// It is here, instead of root_nocgo_darwin.go, so that tests can check it
// even if the tests are run with cgo enabled.
// The linker will not include these unused functions in binaries built with cgo enabled.

// execSecurityRoots finds the macOS list of trusted root certificates
// using only command-line tools. This is our fallback path when cgo isn't available.
//
// The strategy is as follows:
//
// 1. Run "security find-certificate" to dump the list of system root
//    CAs in PEM format.
//
// 2. For each dumped cert, conditionally verify it with "security
//    verify-cert" if that cert was not in the SystemRootCertificates
//    keychain, which can't have custom trust policies.
//
// We need to run "verify-cert" for all certificates not in SystemRootCertificates
// because there might be certificates in the keychains without a corresponding
// trust entry, in which case the logic is complicated (see root_cgo_darwin.go).
//
// TODO: actually parse the "trust-settings-export" output and apply the full
// logic. See Issue 26830.
func execSecurityRoots() (*x509.CertPool, error) {
	keychains := []string{"/Library/Keychains/System.keychain"}

	// Note that this results in trusting roots from $HOME/... (the environment
	// variable), which might not be expected.
	u, err := user.Current()
	if err != nil {
		if debugDarwinRoots {
			fmt.Printf("crypto/x509: get current user: %v\n", err)
		}
	} else {
		keychains = append(keychains,
			filepath.Join(u.HomeDir, "/Library/Keychains/login.keychain"),

			// Fresh installs of Sierra use a slightly different path for the login keychain
			filepath.Join(u.HomeDir, "/Library/Keychains/login.keychain-db"),
		)
	}

	var (
		mu          sync.Mutex
		roots       = x509.NewCertPool()
		numVerified int // number of execs of 'security verify-cert', for debug stats
		wg          sync.WaitGroup
		verifyCh    = make(chan *x509.Certificate)
	)

	// Using 4 goroutines to pipe into verify-cert seems to be
	// about the best we can do. The verify-cert binary seems to
	// just RPC to another server with coarse locking anyway, so
	// running 16 at a time for instance doesn't help at all.
	for i := 0; i < 4; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for cert := range verifyCh {
				valid := verifyCertWithSystem(cert)

				mu.Lock()
				numVerified++
				if valid {
					roots.AddCert(cert)
				}
				mu.Unlock()
			}
		}()
	}
	err = forEachCertInKeychains(keychains, func(cert *x509.Certificate) {
		verifyCh <- cert
	})
	if err != nil {
		return nil, err
	}
	close(verifyCh)
	wg.Wait()

	if debugDarwinRoots {
		fmt.Printf("crypto/x509: ran security verify-cert %d times\n", numVerified)
	}

	err = forEachCertInKeychains([]string{
		"/System/Library/Keychains/SystemRootCertificates.keychain",
	}, roots.AddCert)
	if err != nil {
		return nil, err
	}

	return roots, nil
}

func forEachCertInKeychains(paths []string, f func(*x509.Certificate)) error {
	args := append([]string{"find-certificate", "-a", "-p"}, paths...)
	cmd := exec.Command("/usr/bin/security", args...)
	data, err := cmd.Output()
	if err != nil {
		return err
	}
	for len(data) > 0 {
		var block *pem.Block
		block, data = pem.Decode(data)
		if block == nil {
			break
		}
		if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
			continue
		}
		cert, err := x509.ParseCertificate(block.Bytes)
		if err != nil {
			continue
		}
		f(cert)
	}
	return nil
}

func verifyCertWithSystem(cert *x509.Certificate) bool {
	data := pem.EncodeToMemory(&pem.Block{
		Type: "CERTIFICATE", Bytes: cert.Raw,
	})

	f, err := ioutil.TempFile("", "cert")
	if err != nil {
		fmt.Fprintf(os.Stderr, "can't create temporary file for cert: %v", err)
		return false
	}
	defer os.Remove(f.Name())
	if _, err := f.Write(data); err != nil {
		fmt.Fprintf(os.Stderr, "can't write temporary file for cert: %v", err)
		return false
	}
	if err := f.Close(); err != nil {
		fmt.Fprintf(os.Stderr, "can't write temporary file for cert: %v", err)
		return false
	}
	cmd := exec.Command("/usr/bin/security", "verify-cert", "-p", "ssl", "-c", f.Name(), "-l", "-L")
	var stderr bytes.Buffer
	if debugDarwinRoots {
		cmd.Stderr = &stderr
	}
	if err := cmd.Run(); err != nil {
		if debugDarwinRoots {
			fmt.Printf("crypto/x509: verify-cert rejected %s: %q\n", cert.Subject, bytes.TrimSpace(stderr.Bytes()))
		}
		return false
	}
	if debugDarwinRoots {
		fmt.Printf("crypto/x509: verify-cert approved %s\n", cert.Subject)
	}
	return true
}
