mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
vendor: Update github.com/xenolf/lego/acme to latest
This commit is contained in:
parent
09188981c4
commit
8f583dcf36
10 changed files with 229 additions and 110 deletions
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")
|
||||
)
|
||||
|
|
127
vendor/github.com/xenolf/lego/acme/client.go
generated
vendored
127
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:
|
|||
}
|
||||
}
|
||||
|
||||
// Add the CSR to the certificate so that it can be used for renewals.
|
||||
cert.CSR = pemEncode(&csr)
|
||||
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 {
|
||||
|
|
70
vendor/github.com/xenolf/lego/acme/dns_challenge.go
generated
vendored
70
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"
|
||||
|
@ -18,18 +19,30 @@ type preCheckDNSFunc func(fqdn, value string) (bool, error)
|
|||
var (
|
||||
// PreCheckDNS checks DNS propagation before notifying ACME that
|
||||
// the DNS challenge is ready.
|
||||
PreCheckDNS preCheckDNSFunc = checkDNSPropagation
|
||||
fqdnToZone = map[string]string{}
|
||||
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)
|
||||
if err != nil {
|
||||
log.Warnf("Error cleaning up %s: %v ", domain, err)
|
||||
}
|
||||
}()
|
||||
|
||||
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 {
|
||||
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…
Reference in a new issue