package getproviders

import (
	"bufio"
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"log"
	"strings"

	// TODO: replace crypto/openpgp since it is deprecated
	// https://github.com/golang/go/issues/44226
	//lint:file-ignore SA1019 openpgp is deprecated but there are no good alternatives yet
	"golang.org/x/crypto/openpgp"
	openpgpArmor "golang.org/x/crypto/openpgp/armor"
	openpgpErrors "golang.org/x/crypto/openpgp/errors"
)

type packageAuthenticationResult int

const (
	verifiedChecksum packageAuthenticationResult = iota
	officialProvider
	partnerProvider
	communityProvider
)

// PackageAuthenticationResult is returned from a PackageAuthentication
// implementation. It is a mostly-opaque type intended for use in UI, which
// implements Stringer.
//
// A failed PackageAuthentication attempt will return an "unauthenticated"
// result, which is represented by nil.
type PackageAuthenticationResult struct {
	result packageAuthenticationResult
	KeyID  string
}

func (t *PackageAuthenticationResult) String() string {
	if t == nil {
		return "unauthenticated"
	}
	return []string{
		"verified checksum",
		"signed by HashiCorp",
		"signed by a HashiCorp partner",
		"self-signed",
	}[t.result]
}

// SignedByHashiCorp returns whether the package was authenticated as signed
// by HashiCorp.
func (t *PackageAuthenticationResult) SignedByHashiCorp() bool {
	if t == nil {
		return false
	}
	if t.result == officialProvider {
		return true
	}

	return false
}

// SignedByAnyParty returns whether the package was authenticated as signed
// by either HashiCorp or by a third-party.
func (t *PackageAuthenticationResult) SignedByAnyParty() bool {
	if t == nil {
		return false
	}
	if t.result == officialProvider || t.result == partnerProvider || t.result == communityProvider {
		return true
	}

	return false
}

// ThirdPartySigned returns whether the package was authenticated as signed by a party
// other than HashiCorp.
func (t *PackageAuthenticationResult) ThirdPartySigned() bool {
	if t == nil {
		return false
	}
	if t.result == partnerProvider || t.result == communityProvider {
		return true
	}

	return false
}

// SigningKey represents a key used to sign packages from a registry, along
// with an optional trust signature from the registry operator. These are
// both in ASCII armored OpenPGP format.
//
// The JSON struct tags represent the field names used by the Registry API.
type SigningKey struct {
	ASCIIArmor     string `json:"ascii_armor"`
	TrustSignature string `json:"trust_signature"`
}

// PackageAuthentication is an interface implemented by the optional package
// authentication implementations a source may include on its PackageMeta
// objects.
//
// A PackageAuthentication implementation is responsible for authenticating
// that a package is what its distributor intended to distribute and that it
// has not been tampered with.
type PackageAuthentication interface {
	// AuthenticatePackage takes the local location of a package (which may or
	// may not be the same as the original source location), and returns a
	// PackageAuthenticationResult, or an error if the authentication checks
	// fail.
	//
	// The local location is guaranteed not to be a PackageHTTPURL: a remote
	// package will always be staged locally for inspection first.
	AuthenticatePackage(localLocation PackageLocation) (*PackageAuthenticationResult, error)
}

// PackageAuthenticationHashes is an optional interface implemented by
// PackageAuthentication implementations that are able to return a set of
// hashes they would consider valid if a given PackageLocation referred to
// a package that matched that hash string.
//
// This can be used to record a set of acceptable hashes for a particular
// package in a lock file so that future install operations can determine
// whether the package has changed since its initial installation.
type PackageAuthenticationHashes interface {
	PackageAuthentication

	// AcceptableHashes returns a set of hashes that this authenticator
	// considers to be valid for the current package or, where possible,
	// equivalent packages on other platforms. The order of the items in
	// the result is not significant, and it may contain duplicates
	// that are also not significant.
	//
	// This method's result should only be used to create a "lock" for a
	// particular provider if an earlier call to AuthenticatePackage for
	// the corresponding package succeeded. A caller might choose to apply
	// differing levels of trust for the acceptable hashes depending on
	// the authentication result: a "verified checksum" result only checked
	// that the downloaded package matched what the source claimed, which
	// could be considered to be less trustworthy than a check that includes
	// verifying a signature from the origin registry, depending on what the
	// hashes are going to be used for.
	//
	// Implementations of PackageAuthenticationHashes may return multiple
	// hashes with different schemes, which means that all of them are equally
	// acceptable. Implementors may also return hashes that use schemes the
	// current version of the authenticator would not allow but that could be
	// accepted by other versions of Terraform, e.g. if a particular hash
	// scheme has been deprecated.
	//
	// Authenticators that don't use hashes as their authentication procedure
	// will either not implement this interface or will have an implementation
	// that returns an empty result.
	AcceptableHashes() []Hash
}

type packageAuthenticationAll []PackageAuthentication

// PackageAuthenticationAll combines several authentications together into a
// single check value, which passes only if all of the given ones pass.
//
// The checks are processed in the order given, so a failure of an earlier
// check will prevent execution of a later one.
//
// The returned result is from the last authentication, so callers should
// take care to order the authentications such that the strongest is last.
//
// The returned object also implements the AcceptableHashes method from
// interface PackageAuthenticationHashes, returning the hashes from the
// last of the given checks that indicates at least one acceptable hash,
// or no hashes at all if none of the constituents indicate any. The result
// may therefore be incomplete if there is more than one check that can provide
// hashes and they disagree about which hashes are acceptable.
func PackageAuthenticationAll(checks ...PackageAuthentication) PackageAuthentication {
	return packageAuthenticationAll(checks)
}

func (checks packageAuthenticationAll) AuthenticatePackage(localLocation PackageLocation) (*PackageAuthenticationResult, error) {
	var authResult *PackageAuthenticationResult
	for _, check := range checks {
		var err error
		authResult, err = check.AuthenticatePackage(localLocation)
		if err != nil {
			return authResult, err
		}
	}
	return authResult, nil
}

func (checks packageAuthenticationAll) AcceptableHashes() []Hash {
	// The elements of checks are expected to be ordered so that the strongest
	// one is later in the list, so we'll visit them in reverse order and
	// take the first one that implements the interface and returns a non-empty
	// result.
	for i := len(checks) - 1; i >= 0; i-- {
		check, ok := checks[i].(PackageAuthenticationHashes)
		if !ok {
			continue
		}
		allHashes := check.AcceptableHashes()
		if len(allHashes) > 0 {
			return allHashes
		}
	}
	return nil
}

type packageHashAuthentication struct {
	RequiredHashes []Hash
	AllHashes      []Hash
	Platform       Platform
}

// NewPackageHashAuthentication returns a PackageAuthentication implementation
// that checks whether the contents of the package match whatever subset of the
// given hashes are considered acceptable by the current version of Terraform.
//
// This uses the hash algorithms implemented by functions PackageHash and
// MatchesHash. The PreferredHashes function will select which of the given
// hashes are considered by Terraform to be the strongest verification, and
// authentication succeeds as long as one of those matches.
func NewPackageHashAuthentication(platform Platform, validHashes []Hash) PackageAuthentication {
	requiredHashes := PreferredHashes(validHashes)
	return packageHashAuthentication{
		RequiredHashes: requiredHashes,
		AllHashes:      validHashes,
		Platform:       platform,
	}
}

func (a packageHashAuthentication) AuthenticatePackage(localLocation PackageLocation) (*PackageAuthenticationResult, error) {
	if len(a.RequiredHashes) == 0 {
		// Indicates that none of the hashes given to
		// NewPackageHashAuthentication were considered to be usable by this
		// version of Terraform.
		return nil, fmt.Errorf("this version of Terraform does not support any of the checksum formats given for this provider")
	}

	matches, err := PackageMatchesAnyHash(localLocation, a.RequiredHashes)
	if err != nil {
		return nil, fmt.Errorf("failed to verify provider package checksums: %s", err)
	}

	if matches {
		return &PackageAuthenticationResult{result: verifiedChecksum}, nil
	}
	if len(a.RequiredHashes) == 1 {
		return nil, fmt.Errorf("provider package doesn't match the expected checksum %q", a.RequiredHashes[0].String())
	}
	// It's non-ideal that this doesn't actually list the expected checksums,
	// but in the many-checksum case the message would get pretty unweildy.
	// In practice today we typically use this authenticator only with a
	// single hash returned from a network mirror, so the better message
	// above will prevail in that case. Maybe we'll improve on this somehow
	// if the future introduction of a new hash scheme causes there to more
	// commonly be multiple hashes.
	return nil, fmt.Errorf("provider package doesn't match the any of the expected checksums")
}

func (a packageHashAuthentication) AcceptableHashes() []Hash {
	// In this case we include even hashes the current version of Terraform
	// doesn't prefer, because this result is used for building a lock file
	// and so it's helpful to include older hash formats that other Terraform
	// versions might need in order to do authentication successfully.
	return a.AllHashes
}

type archiveHashAuthentication struct {
	Platform      Platform
	WantSHA256Sum [sha256.Size]byte
}

// NewArchiveChecksumAuthentication returns a PackageAuthentication
// implementation that checks that the original distribution archive matches
// the given hash.
//
// This authentication is suitable only for PackageHTTPURL and
// PackageLocalArchive source locations, because the unpacked layout
// (represented by PackageLocalDir) does not retain access to the original
// source archive. Therefore this authenticator will return an error if its
// given localLocation is not PackageLocalArchive.
//
// NewPackageHashAuthentication is preferable to use when possible because
// it uses the newer hashing scheme (implemented by function PackageHash) that
// can work with both packed and unpacked provider packages.
func NewArchiveChecksumAuthentication(platform Platform, wantSHA256Sum [sha256.Size]byte) PackageAuthentication {
	return archiveHashAuthentication{platform, wantSHA256Sum}
}

func (a archiveHashAuthentication) AuthenticatePackage(localLocation PackageLocation) (*PackageAuthenticationResult, error) {
	archiveLocation, ok := localLocation.(PackageLocalArchive)
	if !ok {
		// A source should not use this authentication type for non-archive
		// locations.
		return nil, fmt.Errorf("cannot check archive hash for non-archive location %s", localLocation)
	}

	gotHash, err := PackageHashLegacyZipSHA(archiveLocation)
	if err != nil {
		return nil, fmt.Errorf("failed to compute checksum for %s: %s", archiveLocation, err)
	}
	wantHash := HashLegacyZipSHAFromSHA(a.WantSHA256Sum)
	if gotHash != wantHash {
		return nil, fmt.Errorf("archive has incorrect checksum %s (expected %s)", gotHash, wantHash)
	}
	return &PackageAuthenticationResult{result: verifiedChecksum}, nil
}

func (a archiveHashAuthentication) AcceptableHashes() []Hash {
	return []Hash{HashLegacyZipSHAFromSHA(a.WantSHA256Sum)}
}

type matchingChecksumAuthentication struct {
	Document      []byte
	Filename      string
	WantSHA256Sum [sha256.Size]byte
}

// NewMatchingChecksumAuthentication returns a PackageAuthentication
// implementation that scans a registry-provided SHA256SUMS document for a
// specified filename, and compares the SHA256 hash against the expected hash.
// This is necessary to ensure that the signed SHA256SUMS document matches the
// declared SHA256 hash for the package, and therefore that a valid signature
// of this document authenticates the package.
//
// This authentication always returns a nil result, since it alone cannot offer
// any assertions about package integrity. It should be combined with other
// authentications to be useful.
func NewMatchingChecksumAuthentication(document []byte, filename string, wantSHA256Sum [sha256.Size]byte) PackageAuthentication {
	return matchingChecksumAuthentication{
		Document:      document,
		Filename:      filename,
		WantSHA256Sum: wantSHA256Sum,
	}
}

func (m matchingChecksumAuthentication) AuthenticatePackage(location PackageLocation) (*PackageAuthenticationResult, error) {
	// Find the checksum in the list with matching filename. The document is
	// in the form "0123456789abcdef filename.zip".
	filename := []byte(m.Filename)
	var checksum []byte
	for _, line := range bytes.Split(m.Document, []byte("\n")) {
		parts := bytes.Fields(line)
		if len(parts) > 1 && bytes.Equal(parts[1], filename) {
			checksum = parts[0]
			break
		}
	}
	if checksum == nil {
		return nil, fmt.Errorf("checksum list has no SHA-256 hash for %q", m.Filename)
	}

	// Decode the ASCII checksum into a byte array for comparison.
	var gotSHA256Sum [sha256.Size]byte
	if _, err := hex.Decode(gotSHA256Sum[:], checksum); err != nil {
		return nil, fmt.Errorf("checksum list has invalid SHA256 hash %q: %s", string(checksum), err)
	}

	// If the checksums don't match, authentication fails.
	if !bytes.Equal(gotSHA256Sum[:], m.WantSHA256Sum[:]) {
		return nil, fmt.Errorf("checksum list has unexpected SHA-256 hash %x (expected %x)", gotSHA256Sum, m.WantSHA256Sum[:])
	}

	// Success! But this doesn't result in any real authentication, only a
	// lack of authentication errors, so we return a nil result.
	return nil, nil
}

type signatureAuthentication struct {
	Document  []byte
	Signature []byte
	Keys      []SigningKey
}

// NewSignatureAuthentication returns a PackageAuthentication implementation
// that verifies the cryptographic signature for a package against any of the
// provided keys.
//
// The signing key for a package will be auto detected by attempting each key
// in turn until one is successful. If such a key is found, there are three
// possible successful authentication results:
//
//  1. If the signing key is the HashiCorp official key, it is an official
//     provider;
//  2. Otherwise, if the signing key has a trust signature from the HashiCorp
//     Partners key, it is a partner provider;
//  3. If neither of the above is true, it is a community provider.
//
// Any failure in the process of validating the signature will result in an
// unauthenticated result.
func NewSignatureAuthentication(document, signature []byte, keys []SigningKey) PackageAuthentication {
	return signatureAuthentication{
		Document:  document,
		Signature: signature,
		Keys:      keys,
	}
}

func (s signatureAuthentication) AuthenticatePackage(location PackageLocation) (*PackageAuthenticationResult, error) {
	// Find the key that signed the checksum file. This can fail if there is no
	// valid signature for any of the provided keys.
	signingKey, keyID, err := s.findSigningKey()
	if err != nil {
		return nil, err
	}

	// Verify the signature using the HashiCorp public key. If this succeeds,
	// this is an official provider.
	hashicorpKeyring, err := openpgp.ReadArmoredKeyRing(strings.NewReader(HashicorpPublicKey))
	if err != nil {
		return nil, fmt.Errorf("error creating HashiCorp keyring: %s", err)
	}
	_, err = openpgp.CheckDetachedSignature(hashicorpKeyring, bytes.NewReader(s.Document), bytes.NewReader(s.Signature))
	if err == nil {
		return &PackageAuthenticationResult{result: officialProvider, KeyID: keyID}, nil
	}

	// If the signing key has a trust signature, attempt to verify it with the
	// HashiCorp partners public key.
	if signingKey.TrustSignature != "" {
		hashicorpPartnersKeyring, err := openpgp.ReadArmoredKeyRing(strings.NewReader(HashicorpPartnersKey))
		if err != nil {
			return nil, fmt.Errorf("error creating HashiCorp Partners keyring: %s", err)
		}

		authorKey, err := openpgpArmor.Decode(strings.NewReader(signingKey.ASCIIArmor))
		if err != nil {
			return nil, fmt.Errorf("error decoding signing key: %s", err)
		}

		trustSignature, err := openpgpArmor.Decode(strings.NewReader(signingKey.TrustSignature))
		if err != nil {
			return nil, fmt.Errorf("error decoding trust signature: %s", err)
		}

		_, err = openpgp.CheckDetachedSignature(hashicorpPartnersKeyring, authorKey.Body, trustSignature.Body)
		if err != nil {
			return nil, fmt.Errorf("error verifying trust signature: %s", err)
		}

		return &PackageAuthenticationResult{result: partnerProvider, KeyID: keyID}, nil
	}

	// We have a valid signature, but it's not from the HashiCorp key, and it
	// also isn't a trusted partner. This is a community provider.
	return &PackageAuthenticationResult{result: communityProvider, KeyID: keyID}, nil
}

func (s signatureAuthentication) AcceptableHashes() []Hash {
	// This is a bit of an abstraction leak because signatureAuthentication
	// otherwise just treats the document as an opaque blob that's been
	// signed, but here we're making assumptions about its format because
	// we only want to trust that _all_ of the checksums are valid (rather
	// than just the current platform's one) if we've also verified that the
	// bag of checksums is signed.
	//
	// In recognition of that layering quirk this implementation is intended to
	// be somewhat resilient to potentially using this authenticator with
	// non-checksums files in future (in which case it'll return nothing at all)
	// but it might be better in the long run to instead combine
	// signatureAuthentication and matchingChecksumAuthentication together and
	// be explicit that the resulting merged authenticator is exclusively for
	// checksums files.

	var ret []Hash
	sc := bufio.NewScanner(bytes.NewReader(s.Document))
	for sc.Scan() {
		parts := bytes.Fields(sc.Bytes())
		if len(parts) != 0 && len(parts) < 2 {
			// Doesn't look like a valid sums file line, so we'll assume
			// this whole thing isn't a checksums file.
			return nil
		}

		// If this is a checksums file then the first part should be a
		// hex-encoded SHA256 hash, so it should be 64 characters long
		// and contain only hex digits.
		hashStr := parts[0]
		if len(hashStr) != 64 {
			return nil // doesn't look like a checksums file
		}

		var gotSHA256Sum [sha256.Size]byte
		if _, err := hex.Decode(gotSHA256Sum[:], hashStr); err != nil {
			return nil // doesn't look like a checksums file
		}

		ret = append(ret, HashLegacyZipSHAFromSHA(gotSHA256Sum))
	}

	return ret
}

// findSigningKey attempts to verify the signature using each of the keys
// returned by the registry. If a valid signature is found, it returns the
// signing key.
//
// Note: currently the registry only returns one key, but this may change in
// the future.
func (s signatureAuthentication) findSigningKey() (*SigningKey, string, error) {
	for _, key := range s.Keys {
		keyring, err := openpgp.ReadArmoredKeyRing(strings.NewReader(key.ASCIIArmor))
		if err != nil {
			return nil, "", fmt.Errorf("error decoding signing key: %s", err)
		}

		entity, err := openpgp.CheckDetachedSignature(keyring, bytes.NewReader(s.Document), bytes.NewReader(s.Signature))

		// If the signature issuer does not match the the key, keep trying the
		// rest of the provided keys.
		if err == openpgpErrors.ErrUnknownIssuer {
			continue
		}

		// Any other signature error is terminal.
		if err != nil {
			return nil, "", fmt.Errorf("error checking signature: %s", err)
		}

		keyID := "n/a"
		if entity.PrimaryKey != nil {
			keyID = entity.PrimaryKey.KeyIdString()
		}

		log.Printf("[DEBUG] Provider signed by %s", entityString(entity))
		return &key, keyID, nil
	}

	// If none of the provided keys issued the signature, this package is
	// unsigned. This is currently a terminal authentication error.
	return nil, "", fmt.Errorf("authentication signature from unknown issuer")
}

// entityString extracts the key ID and identity name(s) from an openpgp.Entity
// for logging.
func entityString(entity *openpgp.Entity) string {
	if entity == nil {
		return ""
	}

	keyID := "n/a"
	if entity.PrimaryKey != nil {
		keyID = entity.PrimaryKey.KeyIdString()
	}

	var names []string
	for _, identity := range entity.Identities {
		names = append(names, identity.Name)
	}

	return fmt.Sprintf("%s %s", keyID, strings.Join(names, ", "))
}
