// Copyright 2018 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 acmetest provides types for testing acme and autocert packages.
//
// TODO: Consider moving this to x/crypto/acme/internal/acmetest for acme tests as well.
package acmetest

import (
	"context"
	"crypto"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/asn1"
	"encoding/base64"
	"encoding/json"
	"encoding/pem"
	"fmt"
	"io"
	"math/big"
	"net"
	"net/http"
	"net/http/httptest"
	"path"
	"strconv"
	"strings"
	"sync"
	"testing"
	"time"

	"golang.org/x/crypto/acme"
)

// CAServer is a simple test server which implements ACME spec bits needed for testing.
type CAServer struct {
	rootKey      crypto.Signer
	rootCert     []byte // DER encoding
	rootTemplate *x509.Certificate

	t              *testing.T
	server         *httptest.Server
	issuer         pkix.Name
	challengeTypes []string
	url            string
	roots          *x509.CertPool
	eabRequired    bool

	mu             sync.Mutex
	certCount      int                           // number of issued certs
	acctRegistered bool                          // set once an account has been registered
	domainAddr     map[string]string             // domain name to addr:port resolution
	domainGetCert  map[string]getCertificateFunc // domain name to GetCertificate function
	domainHandler  map[string]http.Handler       // domain name to Handle function
	validAuthz     map[string]*authorization     // valid authz, keyed by domain name
	authorizations []*authorization              // all authz, index is used as ID
	orders         []*order                      // index is used as order ID
	errors         []error                       // encountered client errors
}

type getCertificateFunc func(hello *tls.ClientHelloInfo) (*tls.Certificate, error)

// NewCAServer creates a new ACME test server. The returned CAServer issues
// certs signed with the CA roots available in the Roots field.
func NewCAServer(t *testing.T) *CAServer {
	ca := &CAServer{t: t,
		challengeTypes: []string{"fake-01", "tls-alpn-01", "http-01"},
		domainAddr:     make(map[string]string),
		domainGetCert:  make(map[string]getCertificateFunc),
		domainHandler:  make(map[string]http.Handler),
		validAuthz:     make(map[string]*authorization),
	}

	ca.server = httptest.NewUnstartedServer(http.HandlerFunc(ca.handle))

	r, err := rand.Int(rand.Reader, big.NewInt(1000000))
	if err != nil {
		panic(fmt.Sprintf("rand.Int: %v", err))
	}
	ca.issuer = pkix.Name{
		Organization: []string{"Test Acme Co"},
		CommonName:   "Root CA " + r.String(),
	}

	return ca
}

func (ca *CAServer) generateRoot() {
	key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	if err != nil {
		panic(fmt.Sprintf("ecdsa.GenerateKey: %v", err))
	}
	tmpl := &x509.Certificate{
		SerialNumber:          big.NewInt(1),
		Subject:               ca.issuer,
		NotBefore:             time.Now(),
		NotAfter:              time.Now().Add(365 * 24 * time.Hour),
		KeyUsage:              x509.KeyUsageCertSign,
		BasicConstraintsValid: true,
		IsCA:                  true,
	}
	der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key)
	if err != nil {
		panic(fmt.Sprintf("x509.CreateCertificate: %v", err))
	}
	cert, err := x509.ParseCertificate(der)
	if err != nil {
		panic(fmt.Sprintf("x509.ParseCertificate: %v", err))
	}
	ca.roots = x509.NewCertPool()
	ca.roots.AddCert(cert)
	ca.rootKey = key
	ca.rootCert = der
	ca.rootTemplate = tmpl
}

// IssuerName sets the name of the issuing CA.
func (ca *CAServer) IssuerName(name pkix.Name) *CAServer {
	if ca.url != "" {
		panic("IssuerName must be called before Start")
	}
	ca.issuer = name
	return ca
}

// ChallengeTypes sets the supported challenge types.
func (ca *CAServer) ChallengeTypes(types ...string) *CAServer {
	if ca.url != "" {
		panic("ChallengeTypes must be called before Start")
	}
	ca.challengeTypes = types
	return ca
}

// URL returns the server address, after Start has been called.
func (ca *CAServer) URL() string {
	if ca.url == "" {
		panic("URL called before Start")
	}
	return ca.url
}

// Roots returns a pool cointaining the CA root.
func (ca *CAServer) Roots() *x509.CertPool {
	if ca.url == "" {
		panic("Roots called before Start")
	}
	return ca.roots
}

// ExternalAccountRequired makes an EAB JWS required for account registration.
func (ca *CAServer) ExternalAccountRequired() *CAServer {
	if ca.url != "" {
		panic("ExternalAccountRequired must be called before Start")
	}
	ca.eabRequired = true
	return ca
}

// Start starts serving requests. The server address becomes available in the
// URL field.
func (ca *CAServer) Start() *CAServer {
	if ca.url == "" {
		ca.generateRoot()
		ca.server.Start()
		ca.t.Cleanup(ca.server.Close)
		ca.url = ca.server.URL
	}
	return ca
}

func (ca *CAServer) serverURL(format string, arg ...interface{}) string {
	return ca.server.URL + fmt.Sprintf(format, arg...)
}

func (ca *CAServer) addr(domain string) (string, bool) {
	ca.mu.Lock()
	defer ca.mu.Unlock()
	addr, ok := ca.domainAddr[domain]
	return addr, ok
}

func (ca *CAServer) getCert(domain string) (getCertificateFunc, bool) {
	ca.mu.Lock()
	defer ca.mu.Unlock()
	f, ok := ca.domainGetCert[domain]
	return f, ok
}

func (ca *CAServer) getHandler(domain string) (http.Handler, bool) {
	ca.mu.Lock()
	defer ca.mu.Unlock()
	h, ok := ca.domainHandler[domain]
	return h, ok
}

func (ca *CAServer) httpErrorf(w http.ResponseWriter, code int, format string, a ...interface{}) {
	s := fmt.Sprintf(format, a...)
	ca.t.Errorf(format, a...)
	http.Error(w, s, code)
}

// Resolve adds a domain to address resolution for the ca to dial to
// when validating challenges for the domain authorization.
func (ca *CAServer) Resolve(domain, addr string) {
	ca.mu.Lock()
	defer ca.mu.Unlock()
	ca.domainAddr[domain] = addr
}

// ResolveGetCertificate redirects TLS connections for domain to f when
// validating challenges for the domain authorization.
func (ca *CAServer) ResolveGetCertificate(domain string, f getCertificateFunc) {
	ca.mu.Lock()
	defer ca.mu.Unlock()
	ca.domainGetCert[domain] = f
}

// ResolveHandler redirects HTTP requests for domain to f when
// validating challenges for the domain authorization.
func (ca *CAServer) ResolveHandler(domain string, h http.Handler) {
	ca.mu.Lock()
	defer ca.mu.Unlock()
	ca.domainHandler[domain] = h
}

type discovery struct {
	NewNonce   string `json:"newNonce"`
	NewAccount string `json:"newAccount"`
	NewOrder   string `json:"newOrder"`
	NewAuthz   string `json:"newAuthz"`

	Meta discoveryMeta `json:"meta,omitempty"`
}

type discoveryMeta struct {
	ExternalAccountRequired bool `json:"externalAccountRequired,omitempty"`
}

type challenge struct {
	URI   string `json:"uri"`
	Type  string `json:"type"`
	Token string `json:"token"`
}

type authorization struct {
	Status     string      `json:"status"`
	Challenges []challenge `json:"challenges"`

	domain string
	id     int
}

type order struct {
	Status      string   `json:"status"`
	AuthzURLs   []string `json:"authorizations"`
	FinalizeURL string   `json:"finalize"`    // CSR submit URL
	CertURL     string   `json:"certificate"` // already issued cert

	leaf []byte // issued cert in DER format
}

func (ca *CAServer) handle(w http.ResponseWriter, r *http.Request) {
	ca.t.Logf("%s %s", r.Method, r.URL)
	w.Header().Set("Replay-Nonce", "nonce")
	// TODO: Verify nonce header for all POST requests.

	switch {
	default:
		ca.httpErrorf(w, http.StatusBadRequest, "unrecognized r.URL.Path: %s", r.URL.Path)

	// Discovery request.
	case r.URL.Path == "/":
		resp := &discovery{
			NewNonce:   ca.serverURL("/new-nonce"),
			NewAccount: ca.serverURL("/new-account"),
			NewOrder:   ca.serverURL("/new-order"),
			Meta: discoveryMeta{
				ExternalAccountRequired: ca.eabRequired,
			},
		}
		if err := json.NewEncoder(w).Encode(resp); err != nil {
			panic(fmt.Sprintf("discovery response: %v", err))
		}

	// Nonce requests.
	case r.URL.Path == "/new-nonce":
		// Nonce values are always set. Nothing else to do.
		return

	// Client key registration request.
	case r.URL.Path == "/new-account":
		ca.mu.Lock()
		defer ca.mu.Unlock()
		if ca.acctRegistered {
			ca.httpErrorf(w, http.StatusServiceUnavailable, "multiple accounts are not implemented")
			return
		}
		ca.acctRegistered = true

		var req struct {
			ExternalAccountBinding json.RawMessage
		}

		if err := decodePayload(&req, r.Body); err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, err.Error())
			return
		}

		if ca.eabRequired && len(req.ExternalAccountBinding) == 0 {
			ca.httpErrorf(w, http.StatusBadRequest, "registration failed: no JWS for EAB")
			return
		}

		// TODO: Check the user account key against a ca.accountKeys?
		w.Header().Set("Location", ca.serverURL("/accounts/1"))
		w.WriteHeader(http.StatusCreated)
		w.Write([]byte("{}"))

	// New order request.
	case r.URL.Path == "/new-order":
		var req struct {
			Identifiers []struct{ Value string }
		}
		if err := decodePayload(&req, r.Body); err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, err.Error())
			return
		}
		ca.mu.Lock()
		defer ca.mu.Unlock()
		o := &order{Status: acme.StatusPending}
		for _, id := range req.Identifiers {
			z := ca.authz(id.Value)
			o.AuthzURLs = append(o.AuthzURLs, ca.serverURL("/authz/%d", z.id))
		}
		orderID := len(ca.orders)
		ca.orders = append(ca.orders, o)
		w.Header().Set("Location", ca.serverURL("/orders/%d", orderID))
		w.WriteHeader(http.StatusCreated)
		if err := json.NewEncoder(w).Encode(o); err != nil {
			panic(err)
		}

	// Existing order status requests.
	case strings.HasPrefix(r.URL.Path, "/orders/"):
		ca.mu.Lock()
		defer ca.mu.Unlock()
		o, err := ca.storedOrder(strings.TrimPrefix(r.URL.Path, "/orders/"))
		if err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, err.Error())
			return
		}
		if err := json.NewEncoder(w).Encode(o); err != nil {
			panic(err)
		}

	// Accept challenge requests.
	case strings.HasPrefix(r.URL.Path, "/challenge/"):
		parts := strings.Split(r.URL.Path, "/")
		typ, id := parts[len(parts)-2], parts[len(parts)-1]
		ca.mu.Lock()
		supported := false
		for _, suppTyp := range ca.challengeTypes {
			if suppTyp == typ {
				supported = true
			}
		}
		a, err := ca.storedAuthz(id)
		ca.mu.Unlock()
		if !supported {
			ca.httpErrorf(w, http.StatusBadRequest, "unsupported challenge: %v", typ)
			return
		}
		if err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, "challenge accept: %v", err)
			return
		}
		ca.validateChallenge(a, typ)
		w.Write([]byte("{}"))

	// Get authorization status requests.
	case strings.HasPrefix(r.URL.Path, "/authz/"):
		var req struct{ Status string }
		decodePayload(&req, r.Body)
		deactivate := req.Status == "deactivated"
		ca.mu.Lock()
		defer ca.mu.Unlock()
		authz, err := ca.storedAuthz(strings.TrimPrefix(r.URL.Path, "/authz/"))
		if err != nil {
			ca.httpErrorf(w, http.StatusNotFound, "%v", err)
			return
		}
		if deactivate {
			// Note we don't invalidate authorized orders as we should.
			authz.Status = "deactivated"
			ca.t.Logf("authz %d is now %s", authz.id, authz.Status)
			ca.updatePendingOrders()
		}
		if err := json.NewEncoder(w).Encode(authz); err != nil {
			panic(fmt.Sprintf("encoding authz %d: %v", authz.id, err))
		}

	// Certificate issuance request.
	case strings.HasPrefix(r.URL.Path, "/new-cert/"):
		ca.mu.Lock()
		defer ca.mu.Unlock()
		orderID := strings.TrimPrefix(r.URL.Path, "/new-cert/")
		o, err := ca.storedOrder(orderID)
		if err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, err.Error())
			return
		}
		if o.Status != acme.StatusReady {
			ca.httpErrorf(w, http.StatusForbidden, "order status: %s", o.Status)
			return
		}
		// Validate CSR request.
		var req struct {
			CSR string `json:"csr"`
		}
		decodePayload(&req, r.Body)
		b, _ := base64.RawURLEncoding.DecodeString(req.CSR)
		csr, err := x509.ParseCertificateRequest(b)
		if err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, err.Error())
			return
		}
		// Issue the certificate.
		der, err := ca.leafCert(csr)
		if err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, "new-cert response: ca.leafCert: %v", err)
			return
		}
		o.leaf = der
		o.CertURL = ca.serverURL("/issued-cert/%s", orderID)
		o.Status = acme.StatusValid
		if err := json.NewEncoder(w).Encode(o); err != nil {
			panic(err)
		}

	// Already issued cert download requests.
	case strings.HasPrefix(r.URL.Path, "/issued-cert/"):
		ca.mu.Lock()
		defer ca.mu.Unlock()
		o, err := ca.storedOrder(strings.TrimPrefix(r.URL.Path, "/issued-cert/"))
		if err != nil {
			ca.httpErrorf(w, http.StatusBadRequest, err.Error())
			return
		}
		if o.Status != acme.StatusValid {
			ca.httpErrorf(w, http.StatusForbidden, "order status: %s", o.Status)
			return
		}
		w.Header().Set("Content-Type", "application/pem-certificate-chain")
		pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: o.leaf})
		pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: ca.rootCert})
	}
}

// storedOrder retrieves a previously created order at index i.
// It requires ca.mu to be locked.
func (ca *CAServer) storedOrder(i string) (*order, error) {
	idx, err := strconv.Atoi(i)
	if err != nil {
		return nil, fmt.Errorf("storedOrder: %v", err)
	}
	if idx < 0 {
		return nil, fmt.Errorf("storedOrder: invalid order index %d", idx)
	}
	if idx > len(ca.orders)-1 {
		return nil, fmt.Errorf("storedOrder: no such order %d", idx)
	}

	ca.updatePendingOrders()
	return ca.orders[idx], nil
}

// storedAuthz retrieves a previously created authz at index i.
// It requires ca.mu to be locked.
func (ca *CAServer) storedAuthz(i string) (*authorization, error) {
	idx, err := strconv.Atoi(i)
	if err != nil {
		return nil, fmt.Errorf("storedAuthz: %v", err)
	}
	if idx < 0 {
		return nil, fmt.Errorf("storedAuthz: invalid authz index %d", idx)
	}
	if idx > len(ca.authorizations)-1 {
		return nil, fmt.Errorf("storedAuthz: no such authz %d", idx)
	}
	return ca.authorizations[idx], nil
}

// authz returns an existing valid authorization for the identifier or creates a
// new one. It requires ca.mu to be locked.
func (ca *CAServer) authz(identifier string) *authorization {
	authz, ok := ca.validAuthz[identifier]
	if !ok {
		authzId := len(ca.authorizations)
		authz = &authorization{
			id:     authzId,
			domain: identifier,
			Status: acme.StatusPending,
		}
		for _, typ := range ca.challengeTypes {
			authz.Challenges = append(authz.Challenges, challenge{
				Type:  typ,
				URI:   ca.serverURL("/challenge/%s/%d", typ, authzId),
				Token: challengeToken(authz.domain, typ, authzId),
			})
		}
		ca.authorizations = append(ca.authorizations, authz)
	}
	return authz
}

// leafCert issues a new certificate.
// It requires ca.mu to be locked.
func (ca *CAServer) leafCert(csr *x509.CertificateRequest) (der []byte, err error) {
	ca.certCount++ // next leaf cert serial number
	leaf := &x509.Certificate{
		SerialNumber:          big.NewInt(int64(ca.certCount)),
		Subject:               pkix.Name{Organization: []string{"Test Acme Co"}},
		NotBefore:             time.Now(),
		NotAfter:              time.Now().Add(90 * 24 * time.Hour),
		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		DNSNames:              csr.DNSNames,
		BasicConstraintsValid: true,
	}
	if len(csr.DNSNames) == 0 {
		leaf.DNSNames = []string{csr.Subject.CommonName}
	}
	return x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, csr.PublicKey, ca.rootKey)
}

// LeafCert issues a leaf certificate.
func (ca *CAServer) LeafCert(name, keyType string, notBefore, notAfter time.Time) *tls.Certificate {
	if ca.url == "" {
		panic("LeafCert called before Start")
	}

	ca.mu.Lock()
	defer ca.mu.Unlock()
	var pk crypto.Signer
	switch keyType {
	case "RSA":
		var err error
		pk, err = rsa.GenerateKey(rand.Reader, 1024)
		if err != nil {
			ca.t.Fatal(err)
		}
	case "ECDSA":
		var err error
		pk, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
		if err != nil {
			ca.t.Fatal(err)
		}
	default:
		panic("LeafCert: unknown key type")
	}
	ca.certCount++ // next leaf cert serial number
	leaf := &x509.Certificate{
		SerialNumber:          big.NewInt(int64(ca.certCount)),
		Subject:               pkix.Name{Organization: []string{"Test Acme Co"}},
		NotBefore:             notBefore,
		NotAfter:              notAfter,
		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		DNSNames:              []string{name},
		BasicConstraintsValid: true,
	}
	der, err := x509.CreateCertificate(rand.Reader, leaf, ca.rootTemplate, pk.Public(), ca.rootKey)
	if err != nil {
		ca.t.Fatal(err)
	}
	return &tls.Certificate{
		Certificate: [][]byte{der},
		PrivateKey:  pk,
	}
}

func (ca *CAServer) validateChallenge(authz *authorization, typ string) {
	var err error
	switch typ {
	case "tls-alpn-01":
		err = ca.verifyALPNChallenge(authz)
	case "http-01":
		err = ca.verifyHTTPChallenge(authz)
	default:
		panic(fmt.Sprintf("validation of %q is not implemented", typ))
	}
	ca.mu.Lock()
	defer ca.mu.Unlock()
	if err != nil {
		authz.Status = "invalid"
	} else {
		authz.Status = "valid"
		ca.validAuthz[authz.domain] = authz
	}
	ca.t.Logf("validated %q for %q, err: %v", typ, authz.domain, err)
	ca.t.Logf("authz %d is now %s", authz.id, authz.Status)

	ca.updatePendingOrders()
}

func (ca *CAServer) updatePendingOrders() {
	// Update all pending orders.
	// An order becomes "ready" if all authorizations are "valid".
	// An order becomes "invalid" if any authorization is "invalid".
	// Status changes: https://tools.ietf.org/html/rfc8555#section-7.1.6
	for i, o := range ca.orders {
		if o.Status != acme.StatusPending {
			continue
		}

		countValid, countInvalid := ca.validateAuthzURLs(o.AuthzURLs, i)
		if countInvalid > 0 {
			o.Status = acme.StatusInvalid
			ca.t.Logf("order %d is now invalid", i)
			continue
		}
		if countValid == len(o.AuthzURLs) {
			o.Status = acme.StatusReady
			o.FinalizeURL = ca.serverURL("/new-cert/%d", i)
			ca.t.Logf("order %d is now ready", i)
		}
	}
}

func (ca *CAServer) validateAuthzURLs(urls []string, orderNum int) (countValid, countInvalid int) {
	for _, zurl := range urls {
		z, err := ca.storedAuthz(path.Base(zurl))
		if err != nil {
			ca.t.Logf("no authz %q for order %d", zurl, orderNum)
			continue
		}
		if z.Status == acme.StatusInvalid {
			countInvalid++
		}
		if z.Status == acme.StatusValid {
			countValid++
		}
	}
	return countValid, countInvalid
}

func (ca *CAServer) verifyALPNChallenge(a *authorization) error {
	const acmeALPNProto = "acme-tls/1"

	addr, haveAddr := ca.addr(a.domain)
	getCert, haveGetCert := ca.getCert(a.domain)
	if !haveAddr && !haveGetCert {
		return fmt.Errorf("no resolution information for %q", a.domain)
	}
	if haveAddr && haveGetCert {
		return fmt.Errorf("overlapping resolution information for %q", a.domain)
	}

	var crt *x509.Certificate
	switch {
	case haveAddr:
		conn, err := tls.Dial("tcp", addr, &tls.Config{
			ServerName:         a.domain,
			InsecureSkipVerify: true,
			NextProtos:         []string{acmeALPNProto},
			MinVersion:         tls.VersionTLS12,
		})
		if err != nil {
			return err
		}
		if v := conn.ConnectionState().NegotiatedProtocol; v != acmeALPNProto {
			return fmt.Errorf("CAServer: verifyALPNChallenge: negotiated proto is %q; want %q", v, acmeALPNProto)
		}
		if n := len(conn.ConnectionState().PeerCertificates); n != 1 {
			return fmt.Errorf("len(PeerCertificates) = %d; want 1", n)
		}
		crt = conn.ConnectionState().PeerCertificates[0]
	case haveGetCert:
		hello := &tls.ClientHelloInfo{
			ServerName: a.domain,
			// TODO: support selecting ECDSA.
			CipherSuites:      []uint16{tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305},
			SupportedProtos:   []string{acme.ALPNProto},
			SupportedVersions: []uint16{tls.VersionTLS12},
		}
		c, err := getCert(hello)
		if err != nil {
			return err
		}
		crt, err = x509.ParseCertificate(c.Certificate[0])
		if err != nil {
			return err
		}
	}

	if err := crt.VerifyHostname(a.domain); err != nil {
		return fmt.Errorf("verifyALPNChallenge: VerifyHostname: %v", err)
	}
	// See RFC 8737, Section 6.1.
	oid := asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31}
	for _, x := range crt.Extensions {
		if x.Id.Equal(oid) {
			// TODO: check the token.
			return nil
		}
	}
	return fmt.Errorf("verifyTokenCert: no id-pe-acmeIdentifier extension found")
}

func (ca *CAServer) verifyHTTPChallenge(a *authorization) error {
	addr, haveAddr := ca.addr(a.domain)
	handler, haveHandler := ca.getHandler(a.domain)
	if !haveAddr && !haveHandler {
		return fmt.Errorf("no resolution information for %q", a.domain)
	}
	if haveAddr && haveHandler {
		return fmt.Errorf("overlapping resolution information for %q", a.domain)
	}

	token := challengeToken(a.domain, "http-01", a.id)
	path := "/.well-known/acme-challenge/" + token

	var body string
	switch {
	case haveAddr:
		t := &http.Transport{
			DialContext: func(ctx context.Context, network, _ string) (net.Conn, error) {
				return (&net.Dialer{}).DialContext(ctx, network, addr)
			},
		}
		req, err := http.NewRequest("GET", "http://"+a.domain+path, nil)
		if err != nil {
			return err
		}
		res, err := t.RoundTrip(req)
		if err != nil {
			return err
		}
		if res.StatusCode != http.StatusOK {
			return fmt.Errorf("http token: w.Code = %d; want %d", res.StatusCode, http.StatusOK)
		}
		b, err := io.ReadAll(res.Body)
		if err != nil {
			return err
		}
		body = string(b)
	case haveHandler:
		r := httptest.NewRequest("GET", path, nil)
		r.Host = a.domain
		w := httptest.NewRecorder()
		handler.ServeHTTP(w, r)
		if w.Code != http.StatusOK {
			return fmt.Errorf("http token: w.Code = %d; want %d", w.Code, http.StatusOK)
		}
		body = w.Body.String()
	}

	if !strings.HasPrefix(body, token) {
		return fmt.Errorf("http token value = %q; want 'token-http-01.' prefix", body)
	}
	return nil
}

func decodePayload(v interface{}, r io.Reader) error {
	var req struct{ Payload string }
	if err := json.NewDecoder(r).Decode(&req); err != nil {
		return err
	}
	payload, err := base64.RawURLEncoding.DecodeString(req.Payload)
	if err != nil {
		return err
	}
	return json.Unmarshal(payload, v)
}

func challengeToken(domain, challType string, authzID int) string {
	return fmt.Sprintf("token-%s-%s-%d", domain, challType, authzID)
}

func unique(a []string) []string {
	seen := make(map[string]bool)
	var res []string
	for _, s := range a {
		if s != "" && !seen[s] {
			seen[s] = true
			res = append(res, s)
		}
	}
	return res
}
