mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-11-04 03:27:23 -05:00 
			
		
		
		
	vendor: Update github.com/xenolf/lego/acme to latest
This commit is contained in:
		
							parent
							
								
									09188981c4
								
							
						
					
					
						commit
						8f583dcf36
					
				
							
								
								
									
										2
									
								
								vendor/github.com/xenolf/lego/acme/challenges.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/xenolf/lego/acme/challenges.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -7,9 +7,11 @@ const (
 | 
			
		||||
	// HTTP01 is the "http-01" ACME challenge https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#http
 | 
			
		||||
	// Note: HTTP01ChallengePath returns the URL path to fulfill this challenge
 | 
			
		||||
	HTTP01 = Challenge("http-01")
 | 
			
		||||
 | 
			
		||||
	// DNS01 is the "dns-01" ACME challenge https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#dns
 | 
			
		||||
	// Note: DNS01Record returns a DNS record which will fulfill this challenge
 | 
			
		||||
	DNS01 = Challenge("dns-01")
 | 
			
		||||
 | 
			
		||||
	// TLSALPN01 is the "tls-alpn-01" ACME challenge https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01
 | 
			
		||||
	TLSALPN01 = Challenge("tls-alpn-01")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										123
									
								
								vendor/github.com/xenolf/lego/acme/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										123
									
								
								vendor/github.com/xenolf/lego/acme/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -26,6 +26,9 @@ const (
 | 
			
		||||
	// “new-reg”, “new-authz” and “new-cert” endpoints. From the documentation the
 | 
			
		||||
	// limitation is 20 requests per second, but using 20 as value doesn't work but 18 do
 | 
			
		||||
	overallRequestLimit = 18
 | 
			
		||||
 | 
			
		||||
	statusValid   = "valid"
 | 
			
		||||
	statusInvalid = "invalid"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// User interface is to be implemented by users of this library.
 | 
			
		||||
@ -41,6 +44,17 @@ type solver interface {
 | 
			
		||||
	Solve(challenge challenge, domain string) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Interface for challenges like dns, where we can set a record in advance for ALL challenges.
 | 
			
		||||
// This saves quite a bit of time vs creating the records and solving them serially.
 | 
			
		||||
type preSolver interface {
 | 
			
		||||
	PreSolve(challenge challenge, domain string) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Interface for challenges like dns, where we can solve all the challenges before to delete them.
 | 
			
		||||
type cleanup interface {
 | 
			
		||||
	CleanUp(challenge challenge, domain string) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type validateFunc func(j *jws, domain, uri string, chlng challenge) error
 | 
			
		||||
 | 
			
		||||
// Client is the user-friendy way to ACME
 | 
			
		||||
@ -374,8 +388,10 @@ DNSNames:
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if cert != nil {
 | 
			
		||||
		// Add the CSR to the certificate so that it can be used for renewals.
 | 
			
		||||
		cert.CSR = pemEncode(&csr)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// do not return an empty failures map, because
 | 
			
		||||
	// it would still be a non-nil error value
 | 
			
		||||
@ -396,7 +412,7 @@ DNSNames:
 | 
			
		||||
// the whole certificate will fail.
 | 
			
		||||
func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto.PrivateKey, mustStaple bool) (*CertificateResource, error) {
 | 
			
		||||
	if len(domains) == 0 {
 | 
			
		||||
		return nil, errors.New("No domains to obtain a certificate for")
 | 
			
		||||
		return nil, errors.New("no domains to obtain a certificate for")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if bundle {
 | 
			
		||||
@ -489,9 +505,9 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b
 | 
			
		||||
	// Start by checking to see if the certificate was based off a CSR, and
 | 
			
		||||
	// use that if it's defined.
 | 
			
		||||
	if len(cert.CSR) > 0 {
 | 
			
		||||
		csr, err := pemDecodeTox509CSR(cert.CSR)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		csr, errP := pemDecodeTox509CSR(cert.CSR)
 | 
			
		||||
		if errP != nil {
 | 
			
		||||
			return nil, errP
 | 
			
		||||
		}
 | 
			
		||||
		newCert, failures := c.ObtainCertificateForCSR(*csr, bundle)
 | 
			
		||||
		return newCert, failures
 | 
			
		||||
@ -524,7 +540,6 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) createOrderForIdentifiers(domains []string) (orderResource, error) {
 | 
			
		||||
 | 
			
		||||
	var identifiers []identifier
 | 
			
		||||
	for _, domain := range domains {
 | 
			
		||||
		identifiers = append(identifiers, identifier{Type: "dns", Value: domain})
 | 
			
		||||
@ -548,29 +563,75 @@ func (c *Client) createOrderForIdentifiers(domains []string) (orderResource, err
 | 
			
		||||
	return orderRes, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// an authz with the solver we have chosen and the index of the challenge associated with it
 | 
			
		||||
type selectedAuthSolver struct {
 | 
			
		||||
	authz          authorization
 | 
			
		||||
	challengeIndex int
 | 
			
		||||
	solver         solver
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Looks through the challenge combinations to find a solvable match.
 | 
			
		||||
// Then solves the challenges in series and returns.
 | 
			
		||||
func (c *Client) solveChallengeForAuthz(authorizations []authorization) error {
 | 
			
		||||
	failures := make(ObtainError)
 | 
			
		||||
 | 
			
		||||
	// loop through the resources, basically through the domains.
 | 
			
		||||
	authSolvers := []*selectedAuthSolver{}
 | 
			
		||||
 | 
			
		||||
	// loop through the resources, basically through the domains. First pass just selects a solver for each authz.
 | 
			
		||||
	for _, authz := range authorizations {
 | 
			
		||||
		if authz.Status == "valid" {
 | 
			
		||||
		if authz.Status == statusValid {
 | 
			
		||||
			// Boulder might recycle recent validated authz (see issue #267)
 | 
			
		||||
			log.Infof("[%s] acme: Authorization already valid; skipping challenge", authz.Identifier.Value)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if i, solvr := c.chooseSolver(authz, authz.Identifier.Value); solvr != nil {
 | 
			
		||||
			authSolvers = append(authSolvers, &selectedAuthSolver{
 | 
			
		||||
				authz:          authz,
 | 
			
		||||
				challengeIndex: i,
 | 
			
		||||
				solver:         solvr,
 | 
			
		||||
			})
 | 
			
		||||
		} else {
 | 
			
		||||
			failures[authz.Identifier.Value] = fmt.Errorf("[%s] acme: Could not determine solvers", authz.Identifier.Value)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		// no solvers - no solving
 | 
			
		||||
		if i, solver := c.chooseSolver(authz, authz.Identifier.Value); solver != nil {
 | 
			
		||||
			err := solver.Solve(authz.Challenges[i], authz.Identifier.Value)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				//c.disableAuthz(authz.Identifier)
 | 
			
		||||
	// for all valid presolvers, first submit the challenges so they have max time to propagate
 | 
			
		||||
	for _, item := range authSolvers {
 | 
			
		||||
		authz := item.authz
 | 
			
		||||
		i := item.challengeIndex
 | 
			
		||||
		if presolver, ok := item.solver.(preSolver); ok {
 | 
			
		||||
			if err := presolver.PreSolve(authz.Challenges[i], authz.Identifier.Value); err != nil {
 | 
			
		||||
				failures[authz.Identifier.Value] = err
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			//c.disableAuthz(authz)
 | 
			
		||||
			failures[authz.Identifier.Value] = fmt.Errorf("[%s] acme: Could not determine solvers", authz.Identifier.Value)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer func() {
 | 
			
		||||
		// clean all created TXT records
 | 
			
		||||
		for _, item := range authSolvers {
 | 
			
		||||
			if clean, ok := item.solver.(cleanup); ok {
 | 
			
		||||
				if failures[item.authz.Identifier.Value] != nil {
 | 
			
		||||
					// already failed in previous loop
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				err := clean.CleanUp(item.authz.Challenges[item.challengeIndex], item.authz.Identifier.Value)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					log.Warnf("Error cleaning up %s: %v ", item.authz.Identifier.Value, err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	// finally solve all challenges for real
 | 
			
		||||
	for _, item := range authSolvers {
 | 
			
		||||
		authz := item.authz
 | 
			
		||||
		i := item.challengeIndex
 | 
			
		||||
		if failures[authz.Identifier.Value] != nil {
 | 
			
		||||
			// already failed in previous loop
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if err := item.solver.Solve(authz.Challenges[i], authz.Identifier.Value); err != nil {
 | 
			
		||||
			failures[authz.Identifier.Value] = err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -604,7 +665,7 @@ func (c *Client) getAuthzForOrder(order orderResource) ([]authorization, error)
 | 
			
		||||
 | 
			
		||||
		go func(authzURL string) {
 | 
			
		||||
			var authz authorization
 | 
			
		||||
			_, err := getJSON(authzURL, &authz)
 | 
			
		||||
			_, err := postAsGet(c.jws, authzURL, &authz)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				errc <- domainError{Domain: authz.Identifier.Value, Error: err}
 | 
			
		||||
				return
 | 
			
		||||
@ -696,7 +757,7 @@ func (c *Client) requestCertificateForCsr(order orderResource, bundle bool, csr
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if retOrder.Status == "invalid" {
 | 
			
		||||
	if retOrder.Status == statusInvalid {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -706,7 +767,7 @@ func (c *Client) requestCertificateForCsr(order orderResource, bundle bool, csr
 | 
			
		||||
		PrivateKey: privateKeyPem,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if retOrder.Status == "valid" {
 | 
			
		||||
	if retOrder.Status == statusValid {
 | 
			
		||||
		// if the certificate is available right away, short cut!
 | 
			
		||||
		ok, err := c.checkCertResponse(retOrder, &certRes, bundle)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
@ -728,7 +789,7 @@ func (c *Client) requestCertificateForCsr(order orderResource, bundle bool, csr
 | 
			
		||||
		case <-stopTimer.C:
 | 
			
		||||
			return nil, errors.New("certificate polling timed out")
 | 
			
		||||
		case <-retryTick.C:
 | 
			
		||||
			_, err := getJSON(order.URL, &retOrder)
 | 
			
		||||
			_, err := postAsGet(c.jws, order.URL, &retOrder)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
@ -750,10 +811,9 @@ func (c *Client) requestCertificateForCsr(order orderResource, bundle bool, csr
 | 
			
		||||
// should already have the Domain (common name) field populated. If bundle is
 | 
			
		||||
// true, the certificate will be bundled with the issuer's cert.
 | 
			
		||||
func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResource, bundle bool) (bool, error) {
 | 
			
		||||
 | 
			
		||||
	switch order.Status {
 | 
			
		||||
	case "valid":
 | 
			
		||||
		resp, err := httpGet(order.Certificate)
 | 
			
		||||
	case statusValid:
 | 
			
		||||
		resp, err := postAsGet(c.jws, order.Certificate, nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return false, err
 | 
			
		||||
		}
 | 
			
		||||
@ -801,7 +861,7 @@ func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResou
 | 
			
		||||
 | 
			
		||||
	case "processing":
 | 
			
		||||
		return false, nil
 | 
			
		||||
	case "invalid":
 | 
			
		||||
	case statusInvalid:
 | 
			
		||||
		return false, errors.New("order has invalid state: invalid")
 | 
			
		||||
	default:
 | 
			
		||||
		return false, nil
 | 
			
		||||
@ -811,7 +871,7 @@ func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResou
 | 
			
		||||
// getIssuerCertificate requests the issuer certificate
 | 
			
		||||
func (c *Client) getIssuerCertificate(url string) ([]byte, error) {
 | 
			
		||||
	log.Infof("acme: Requesting issuer cert from %s", url)
 | 
			
		||||
	resp, err := httpGet(url)
 | 
			
		||||
	resp, err := postAsGet(c.jws, url, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@ -854,7 +914,10 @@ func parseLinks(links []string) map[string]string {
 | 
			
		||||
func validate(j *jws, domain, uri string, c challenge) error {
 | 
			
		||||
	var chlng challenge
 | 
			
		||||
 | 
			
		||||
	hdr, err := postJSON(j, uri, c, &chlng)
 | 
			
		||||
	// Challenge initiation is done by sending a JWS payload containing the
 | 
			
		||||
	// trivial JSON object `{}`. We use an empty struct instance as the postJSON
 | 
			
		||||
	// payload here to achieve this result.
 | 
			
		||||
	hdr, err := postJSON(j, uri, struct{}{}, &chlng)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@ -863,12 +926,12 @@ func validate(j *jws, domain, uri string, c challenge) error {
 | 
			
		||||
	// Repeatedly check the server for an updated status on our request.
 | 
			
		||||
	for {
 | 
			
		||||
		switch chlng.Status {
 | 
			
		||||
		case "valid":
 | 
			
		||||
		case statusValid:
 | 
			
		||||
			log.Infof("[%s] The server validated our request", domain)
 | 
			
		||||
			return nil
 | 
			
		||||
		case "pending":
 | 
			
		||||
		case "processing":
 | 
			
		||||
		case "invalid":
 | 
			
		||||
		case statusInvalid:
 | 
			
		||||
			return handleChallengeError(chlng)
 | 
			
		||||
		default:
 | 
			
		||||
			return errors.New("the server returned an unexpected state")
 | 
			
		||||
@ -880,11 +943,15 @@ func validate(j *jws, domain, uri string, c challenge) error {
 | 
			
		||||
			// If it doesn't, we'll just poll hard.
 | 
			
		||||
			ra = 5
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		time.Sleep(time.Duration(ra) * time.Second)
 | 
			
		||||
 | 
			
		||||
		hdr, err = getJSON(uri, &chlng)
 | 
			
		||||
		resp, err := postAsGet(j, uri, &chlng)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if resp != nil {
 | 
			
		||||
			hdr = resp.Header
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										27
									
								
								vendor/github.com/xenolf/lego/acme/crypto.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								vendor/github.com/xenolf/lego/acme/crypto.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -81,20 +81,20 @@ func GetOCSPForCert(bundle []byte) ([]byte, *ocsp.Response, error) {
 | 
			
		||||
			return nil, nil, errors.New("no issuing certificate URL")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		resp, err := httpGet(issuedCert.IssuingCertificateURL[0])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, nil, err
 | 
			
		||||
		resp, errC := httpGet(issuedCert.IssuingCertificateURL[0])
 | 
			
		||||
		if errC != nil {
 | 
			
		||||
			return nil, nil, errC
 | 
			
		||||
		}
 | 
			
		||||
		defer resp.Body.Close()
 | 
			
		||||
 | 
			
		||||
		issuerBytes, err := ioutil.ReadAll(limitReader(resp.Body, 1024*1024))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, nil, err
 | 
			
		||||
		issuerBytes, errC := ioutil.ReadAll(limitReader(resp.Body, 1024*1024))
 | 
			
		||||
		if errC != nil {
 | 
			
		||||
			return nil, nil, errC
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		issuerCert, err := x509.ParseCertificate(issuerBytes)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, nil, err
 | 
			
		||||
		issuerCert, errC := x509.ParseCertificate(issuerBytes)
 | 
			
		||||
		if errC != nil {
 | 
			
		||||
			return nil, nil, errC
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Insert it into the slice on position 0
 | 
			
		||||
@ -258,15 +258,6 @@ func pemDecode(data []byte) (*pem.Block, error) {
 | 
			
		||||
	return pemBlock, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func pemDecodeTox509(pem []byte) (*x509.Certificate, error) {
 | 
			
		||||
	pemBlock, err := pemDecode(pem)
 | 
			
		||||
	if pemBlock == nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return x509.ParseCertificate(pemBlock.Bytes)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func pemDecodeTox509CSR(pem []byte) (*x509.CertificateRequest, error) {
 | 
			
		||||
	pemBlock, err := pemDecode(pem)
 | 
			
		||||
	if pemBlock == nil {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										62
									
								
								vendor/github.com/xenolf/lego/acme/dns_challenge.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										62
									
								
								vendor/github.com/xenolf/lego/acme/dns_challenge.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -7,6 +7,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/miekg/dns"
 | 
			
		||||
@ -20,16 +21,28 @@ var (
 | 
			
		||||
	// the DNS challenge is ready.
 | 
			
		||||
	PreCheckDNS  preCheckDNSFunc = checkDNSPropagation
 | 
			
		||||
	fqdnToZone                   = map[string]string{}
 | 
			
		||||
	muFqdnToZone sync.Mutex
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const defaultResolvConf = "/etc/resolv.conf"
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// DefaultPropagationTimeout default propagation timeout
 | 
			
		||||
	DefaultPropagationTimeout = 60 * time.Second
 | 
			
		||||
 | 
			
		||||
	// DefaultPollingInterval default polling interval
 | 
			
		||||
	DefaultPollingInterval = 2 * time.Second
 | 
			
		||||
 | 
			
		||||
	// DefaultTTL default TTL
 | 
			
		||||
	DefaultTTL = 120
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var defaultNameservers = []string{
 | 
			
		||||
	"google-public-dns-a.google.com:53",
 | 
			
		||||
	"google-public-dns-b.google.com:53",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RecursiveNameservers are used to pre-check DNS propagations
 | 
			
		||||
// RecursiveNameservers are used to pre-check DNS propagation
 | 
			
		||||
var RecursiveNameservers = getNameservers(defaultResolvConf, defaultNameservers)
 | 
			
		||||
 | 
			
		||||
// DNSTimeout is used to override the default DNS timeout of 10 seconds.
 | 
			
		||||
@ -59,7 +72,7 @@ func DNS01Record(domain, keyAuth string) (fqdn string, value string, ttl int) {
 | 
			
		||||
	keyAuthShaBytes := sha256.Sum256([]byte(keyAuth))
 | 
			
		||||
	// base64URL encoding without padding
 | 
			
		||||
	value = base64.RawURLEncoding.EncodeToString(keyAuthShaBytes[:sha256.Size])
 | 
			
		||||
	ttl = 120
 | 
			
		||||
	ttl = DefaultTTL
 | 
			
		||||
	fqdn = fmt.Sprintf("_acme-challenge.%s.", domain)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
@ -71,8 +84,10 @@ type dnsChallenge struct {
 | 
			
		||||
	provider ChallengeProvider
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *dnsChallenge) Solve(chlng challenge, domain string) error {
 | 
			
		||||
	log.Infof("[%s] acme: Trying to solve DNS-01", domain)
 | 
			
		||||
// PreSolve just submits the txt record to the dns provider. It does not validate record propagation, or
 | 
			
		||||
// do anything at all with the acme server.
 | 
			
		||||
func (s *dnsChallenge) PreSolve(chlng challenge, domain string) error {
 | 
			
		||||
	log.Infof("[%s] acme: Preparing to solve DNS-01", domain)
 | 
			
		||||
 | 
			
		||||
	if s.provider == nil {
 | 
			
		||||
		return errors.New("no DNS Provider configured")
 | 
			
		||||
@ -88,12 +103,18 @@ func (s *dnsChallenge) Solve(chlng challenge, domain string) error {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("error presenting token: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer func() {
 | 
			
		||||
		err := s.provider.CleanUp(domain, chlng.Token, keyAuth)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *dnsChallenge) Solve(chlng challenge, domain string) error {
 | 
			
		||||
	log.Infof("[%s] acme: Trying to solve DNS-01", domain)
 | 
			
		||||
 | 
			
		||||
	// Generate the Key Authorization for the challenge
 | 
			
		||||
	keyAuth, err := getKeyAuthorization(chlng.Token, s.jws.privKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
			log.Warnf("Error cleaning up %s: %v ", domain, err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	fqdn, value, _ := DNS01Record(domain, keyAuth)
 | 
			
		||||
 | 
			
		||||
@ -104,7 +125,7 @@ func (s *dnsChallenge) Solve(chlng challenge, domain string) error {
 | 
			
		||||
	case ChallengeProviderTimeout:
 | 
			
		||||
		timeout, interval = provider.Timeout()
 | 
			
		||||
	default:
 | 
			
		||||
		timeout, interval = 60*time.Second, 2*time.Second
 | 
			
		||||
		timeout, interval = DefaultPropagationTimeout, DefaultPollingInterval
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = WaitFor(timeout, interval, func() (bool, error) {
 | 
			
		||||
@ -117,6 +138,15 @@ func (s *dnsChallenge) Solve(chlng challenge, domain string) error {
 | 
			
		||||
	return s.validate(s.jws, domain, chlng.URL, challenge{Type: chlng.Type, Token: chlng.Token, KeyAuthorization: keyAuth})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CleanUp cleans the challenge
 | 
			
		||||
func (s *dnsChallenge) CleanUp(chlng challenge, domain string) error {
 | 
			
		||||
	keyAuth, err := getKeyAuthorization(chlng.Token, s.jws.privKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return s.provider.CleanUp(domain, chlng.Token, keyAuth)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// checkDNSPropagation checks if the expected TXT record has been propagated to all authoritative nameservers.
 | 
			
		||||
func checkDNSPropagation(fqdn, value string) (bool, error) {
 | 
			
		||||
	// Initial attempt to resolve at the recursive NS
 | 
			
		||||
@ -124,6 +154,7 @@ func checkDNSPropagation(fqdn, value string) (bool, error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if r.Rcode == dns.RcodeSuccess {
 | 
			
		||||
		// If we see a CNAME here then use the alias
 | 
			
		||||
		for _, rr := range r.Answer {
 | 
			
		||||
@ -167,7 +198,7 @@ func checkAuthoritativeNss(fqdn, value string, nameservers []string) (bool, erro
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !found {
 | 
			
		||||
			return false, fmt.Errorf("NS %s did not return the expected TXT record", ns)
 | 
			
		||||
			return false, fmt.Errorf("NS %s did not return the expected TXT record [fqdn: %s]", ns, fqdn)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -210,7 +241,7 @@ func lookupNameservers(fqdn string) ([]string, error) {
 | 
			
		||||
 | 
			
		||||
	zone, err := FindZoneByFqdn(fqdn, RecursiveNameservers)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("Could not determine the zone: %v", err)
 | 
			
		||||
		return nil, fmt.Errorf("could not determine the zone: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r, err := dnsQuery(zone, dns.TypeNS, RecursiveNameservers, true)
 | 
			
		||||
@ -227,12 +258,15 @@ func lookupNameservers(fqdn string) ([]string, error) {
 | 
			
		||||
	if len(authoritativeNss) > 0 {
 | 
			
		||||
		return authoritativeNss, nil
 | 
			
		||||
	}
 | 
			
		||||
	return nil, fmt.Errorf("Could not determine authoritative nameservers")
 | 
			
		||||
	return nil, fmt.Errorf("could not determine authoritative nameservers")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindZoneByFqdn determines the zone apex for the given fqdn by recursing up the
 | 
			
		||||
// domain labels until the nameserver returns a SOA record in the answer section.
 | 
			
		||||
func FindZoneByFqdn(fqdn string, nameservers []string) (string, error) {
 | 
			
		||||
	muFqdnToZone.Lock()
 | 
			
		||||
	defer muFqdnToZone.Unlock()
 | 
			
		||||
 | 
			
		||||
	// Do we have it cached?
 | 
			
		||||
	if zone, ok := fqdnToZone[fqdn]; ok {
 | 
			
		||||
		return zone, nil
 | 
			
		||||
@ -249,7 +283,7 @@ func FindZoneByFqdn(fqdn string, nameservers []string) (string, error) {
 | 
			
		||||
 | 
			
		||||
		// Any response code other than NOERROR and NXDOMAIN is treated as error
 | 
			
		||||
		if in.Rcode != dns.RcodeNameError && in.Rcode != dns.RcodeSuccess {
 | 
			
		||||
			return "", fmt.Errorf("Unexpected response code '%s' for %s",
 | 
			
		||||
			return "", fmt.Errorf("unexpected response code '%s' for %s",
 | 
			
		||||
				dns.RcodeToString[in.Rcode], domain)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -272,7 +306,7 @@ func FindZoneByFqdn(fqdn string, nameservers []string) (string, error) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return "", fmt.Errorf("Could not find the start of authority")
 | 
			
		||||
	return "", fmt.Errorf("could not find the start of authority")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// dnsMsgContainsCNAME checks for a CNAME answer in msg
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										64
									
								
								vendor/github.com/xenolf/lego/acme/http.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										64
									
								
								vendor/github.com/xenolf/lego/acme/http.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -42,12 +42,14 @@ var (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// defaultGoUserAgent is the Go HTTP package user agent string. Too
 | 
			
		||||
	// bad it isn't exported. If it changes, we should update it here, too.
 | 
			
		||||
	defaultGoUserAgent = "Go-http-client/1.1"
 | 
			
		||||
 | 
			
		||||
	// ourUserAgent is the User-Agent of this underlying library package.
 | 
			
		||||
	ourUserAgent = "xenolf-acme"
 | 
			
		||||
	// NOTE: Update this with each tagged release.
 | 
			
		||||
	ourUserAgent = "xenolf-acme/1.2.1"
 | 
			
		||||
 | 
			
		||||
	// ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package.
 | 
			
		||||
	// values: detach|release
 | 
			
		||||
	// NOTE: Update this with each tagged release.
 | 
			
		||||
	ourUserAgentComment = "detach"
 | 
			
		||||
 | 
			
		||||
	// caCertificatesEnvVar is the environment variable name that can be used to
 | 
			
		||||
	// specify the path to PEM encoded CA Certificates that can be used to
 | 
			
		||||
@ -148,59 +150,63 @@ func getJSON(uri string, respBody interface{}) (http.Header, error) {
 | 
			
		||||
func postJSON(j *jws, uri string, reqBody, respBody interface{}) (http.Header, error) {
 | 
			
		||||
	jsonBytes, err := json.Marshal(reqBody)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.New("Failed to marshal network message")
 | 
			
		||||
		return nil, errors.New("failed to marshal network message")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp, err := j.post(uri, jsonBytes)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("Failed to post JWS message. -> %v", err)
 | 
			
		||||
	resp, err := post(j, uri, jsonBytes, respBody)
 | 
			
		||||
	if resp == nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
 | 
			
		||||
	return resp.Header, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func postAsGet(j *jws, uri string, respBody interface{}) (*http.Response, error) {
 | 
			
		||||
	return post(j, uri, []byte{}, respBody)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func post(j *jws, uri string, reqBody []byte, respBody interface{}) (*http.Response, error) {
 | 
			
		||||
	resp, err := j.post(uri, reqBody)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("failed to post JWS message. -> %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if resp.StatusCode >= http.StatusBadRequest {
 | 
			
		||||
 | 
			
		||||
		err := handleHTTPError(resp)
 | 
			
		||||
 | 
			
		||||
		err = handleHTTPError(resp)
 | 
			
		||||
		switch err.(type) {
 | 
			
		||||
 | 
			
		||||
		case NonceError:
 | 
			
		||||
 | 
			
		||||
			// Retry once if the nonce was invalidated
 | 
			
		||||
 | 
			
		||||
			retryResp, err := j.post(uri, jsonBytes)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, fmt.Errorf("Failed to post JWS message. -> %v", err)
 | 
			
		||||
			retryResp, errP := j.post(uri, reqBody)
 | 
			
		||||
			if errP != nil {
 | 
			
		||||
				return nil, fmt.Errorf("failed to post JWS message. -> %v", errP)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			defer retryResp.Body.Close()
 | 
			
		||||
 | 
			
		||||
			if retryResp.StatusCode >= http.StatusBadRequest {
 | 
			
		||||
				return retryResp.Header, handleHTTPError(retryResp)
 | 
			
		||||
				return retryResp, handleHTTPError(retryResp)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if respBody == nil {
 | 
			
		||||
				return retryResp.Header, nil
 | 
			
		||||
				return retryResp, nil
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return retryResp.Header, json.NewDecoder(retryResp.Body).Decode(respBody)
 | 
			
		||||
 | 
			
		||||
			return retryResp, json.NewDecoder(retryResp.Body).Decode(respBody)
 | 
			
		||||
		default:
 | 
			
		||||
			return resp.Header, err
 | 
			
		||||
 | 
			
		||||
			return resp, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if respBody == nil {
 | 
			
		||||
		return resp.Header, nil
 | 
			
		||||
		return resp, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return resp.Header, json.NewDecoder(resp.Body).Decode(respBody)
 | 
			
		||||
	return resp, json.NewDecoder(resp.Body).Decode(respBody)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// userAgent builds and returns the User-Agent string to use in requests.
 | 
			
		||||
func userAgent() string {
 | 
			
		||||
	ua := fmt.Sprintf("%s %s (%s; %s) %s", UserAgent, ourUserAgent, runtime.GOOS, runtime.GOARCH, defaultGoUserAgent)
 | 
			
		||||
	ua := fmt.Sprintf("%s %s (%s; %s; %s)", UserAgent, ourUserAgent, ourUserAgentComment, runtime.GOOS, runtime.GOARCH)
 | 
			
		||||
	return strings.TrimSpace(ua)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										25
									
								
								vendor/github.com/xenolf/lego/acme/http_challenge_server.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/xenolf/lego/acme/http_challenge_server.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -35,7 +35,7 @@ func (s *HTTPProviderServer) Present(domain, token, keyAuth string) error {
 | 
			
		||||
	var err error
 | 
			
		||||
	s.listener, err = net.Listen("tcp", net.JoinHostPort(s.iface, s.port))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("Could not start HTTP server for challenge -> %v", err)
 | 
			
		||||
		return fmt.Errorf("could not start HTTP server for challenge -> %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.done = make(chan bool)
 | 
			
		||||
@ -62,20 +62,31 @@ func (s *HTTPProviderServer) serve(domain, token, keyAuth string) {
 | 
			
		||||
	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		if strings.HasPrefix(r.Host, domain) && r.Method == http.MethodGet {
 | 
			
		||||
			w.Header().Add("Content-Type", "text/plain")
 | 
			
		||||
			w.Write([]byte(keyAuth))
 | 
			
		||||
			_, err := w.Write([]byte(keyAuth))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			log.Infof("[%s] Served key authentication", domain)
 | 
			
		||||
		} else {
 | 
			
		||||
			log.Warnf("Received request for domain %s with method %s but the domain did not match any challenge. Please ensure your are passing the HOST header properly.", r.Host, r.Method)
 | 
			
		||||
			w.Write([]byte("TEST"))
 | 
			
		||||
			_, err := w.Write([]byte("TEST"))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	httpServer := &http.Server{
 | 
			
		||||
		Handler: mux,
 | 
			
		||||
	}
 | 
			
		||||
	httpServer := &http.Server{Handler: mux}
 | 
			
		||||
 | 
			
		||||
	// Once httpServer is shut down we don't want any lingering
 | 
			
		||||
	// connections, so disable KeepAlives.
 | 
			
		||||
	httpServer.SetKeepAlivesEnabled(false)
 | 
			
		||||
	httpServer.Serve(s.listener)
 | 
			
		||||
 | 
			
		||||
	err := httpServer.Serve(s.listener)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println(err)
 | 
			
		||||
	}
 | 
			
		||||
	s.done <- true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								vendor/github.com/xenolf/lego/acme/tls_alpn_challenge.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/xenolf/lego/acme/tls_alpn_challenge.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -12,8 +12,8 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// idPeAcmeIdentifierV1 is the SMI Security for PKIX Certification Extension OID referencing the ACME extension.
 | 
			
		||||
// Reference: https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01#section-5.1
 | 
			
		||||
var idPeAcmeIdentifierV1 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 30, 1}
 | 
			
		||||
// Reference: https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05#section-5.1
 | 
			
		||||
var idPeAcmeIdentifierV1 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31}
 | 
			
		||||
 | 
			
		||||
type tlsALPNChallenge struct {
 | 
			
		||||
	jws      *jws
 | 
			
		||||
@ -58,7 +58,7 @@ func TLSALPNChallengeBlocks(domain, keyAuth string) ([]byte, []byte, error) {
 | 
			
		||||
 | 
			
		||||
	// Add the keyAuth digest as the acmeValidation-v1 extension
 | 
			
		||||
	// (marked as critical such that it won't be used by non-ACME software).
 | 
			
		||||
	// Reference: https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01#section-3
 | 
			
		||||
	// Reference: https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05#section-3
 | 
			
		||||
	extensions := []pkix.Extension{
 | 
			
		||||
		{
 | 
			
		||||
			Id:       idPeAcmeIdentifierV1,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								vendor/github.com/xenolf/lego/acme/tls_alpn_challenge_server.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/xenolf/lego/acme/tls_alpn_challenge_server.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -3,6 +3,7 @@ package acme
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
)
 | 
			
		||||
@ -65,7 +66,10 @@ func (t *TLSALPNProviderServer) Present(domain, token, keyAuth string) error {
 | 
			
		||||
 | 
			
		||||
	// Shut the server down when we're finished.
 | 
			
		||||
	go func() {
 | 
			
		||||
		http.Serve(t.listener, nil)
 | 
			
		||||
		err := http.Serve(t.listener, nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Println(err)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								vendor/github.com/xenolf/lego/acme/utils.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/xenolf/lego/acme/utils.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -3,16 +3,20 @@ package acme
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/xenolf/lego/log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// WaitFor polls the given function 'f', once every 'interval', up to 'timeout'.
 | 
			
		||||
func WaitFor(timeout, interval time.Duration, f func() (bool, error)) error {
 | 
			
		||||
	log.Infof("Wait [timeout: %s, interval: %s]", timeout, interval)
 | 
			
		||||
 | 
			
		||||
	var lastErr string
 | 
			
		||||
	timeup := time.After(timeout)
 | 
			
		||||
	timeUp := time.After(timeout)
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-timeup:
 | 
			
		||||
			return fmt.Errorf("Time limit exceeded. Last error: %s", lastErr)
 | 
			
		||||
		case <-timeUp:
 | 
			
		||||
			return fmt.Errorf("time limit exceeded: last error: %s", lastErr)
 | 
			
		||||
		default:
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/manifest
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/manifest
									
									
									
									
										vendored
									
									
								
							@ -170,7 +170,7 @@
 | 
			
		||||
			"importpath": "github.com/xenolf/lego/acme",
 | 
			
		||||
			"repository": "https://github.com/xenolf/lego",
 | 
			
		||||
			"vcs": "git",
 | 
			
		||||
			"revision": "04e2d74406d42a3727e7a132c1a39735ac527f51",
 | 
			
		||||
			"revision": "4e842a5eb6dcb9520e03db70cd5896f1df14b72a",
 | 
			
		||||
			"branch": "master",
 | 
			
		||||
			"path": "/acme",
 | 
			
		||||
			"notests": true
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user