Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
caddy
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
caddy
Commits
8f583dcf
Commit
8f583dcf
authored
Dec 05, 2018
by
Matthew Holt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
vendor: Update github.com/xenolf/lego/acme to latest
parent
09188981
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
228 additions
and
109 deletions
+228
-109
vendor/github.com/xenolf/lego/acme/challenges.go
vendor/github.com/xenolf/lego/acme/challenges.go
+2
-0
vendor/github.com/xenolf/lego/acme/client.go
vendor/github.com/xenolf/lego/acme/client.go
+97
-30
vendor/github.com/xenolf/lego/acme/crypto.go
vendor/github.com/xenolf/lego/acme/crypto.go
+9
-18
vendor/github.com/xenolf/lego/acme/dns_challenge.go
vendor/github.com/xenolf/lego/acme/dns_challenge.go
+52
-18
vendor/github.com/xenolf/lego/acme/http.go
vendor/github.com/xenolf/lego/acme/http.go
+34
-28
vendor/github.com/xenolf/lego/acme/http_challenge_server.go
vendor/github.com/xenolf/lego/acme/http_challenge_server.go
+18
-7
vendor/github.com/xenolf/lego/acme/tls_alpn_challenge.go
vendor/github.com/xenolf/lego/acme/tls_alpn_challenge.go
+3
-3
vendor/github.com/xenolf/lego/acme/tls_alpn_challenge_server.go
.../github.com/xenolf/lego/acme/tls_alpn_challenge_server.go
+5
-1
vendor/github.com/xenolf/lego/acme/utils.go
vendor/github.com/xenolf/lego/acme/utils.go
+7
-3
vendor/manifest
vendor/manifest
+1
-1
No files found.
vendor/github.com/xenolf/lego/acme/challenges.go
View file @
8f583dcf
...
...
@@ -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"
)
)
vendor/github.com/xenolf/lego/acme/client.go
View file @
8f583dcf
...
...
@@ -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
(
"
N
o domains to obtain a certificate for"
)
return
nil
,
errors
.
New
(
"
n
o 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
,
err
P
:=
pemDecodeTox509CSR
(
cert
.
CSR
)
if
err
P
!=
nil
{
return
nil
,
err
P
}
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
(
ur
l
)
resp
,
err
:=
postAsGet
(
c
.
jws
,
url
,
ni
l
)
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
}
}
}
vendor/github.com/xenolf/lego/acme/crypto.go
View file @
8f583dcf
...
...
@@ -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
,
err
C
:=
httpGet
(
issuedCert
.
IssuingCertificateURL
[
0
])
if
err
C
!=
nil
{
return
nil
,
nil
,
err
C
}
defer
resp
.
Body
.
Close
()
issuerBytes
,
err
:=
ioutil
.
ReadAll
(
limitReader
(
resp
.
Body
,
1024
*
1024
))
if
err
!=
nil
{
return
nil
,
nil
,
err
issuerBytes
,
err
C
:=
ioutil
.
ReadAll
(
limitReader
(
resp
.
Body
,
1024
*
1024
))
if
err
C
!=
nil
{
return
nil
,
nil
,
err
C
}
issuerCert
,
err
:=
x509
.
ParseCertificate
(
issuerBytes
)
if
err
!=
nil
{
return
nil
,
nil
,
err
issuerCert
,
err
C
:=
x509
.
ParseCertificate
(
issuerBytes
)
if
err
C
!=
nil
{
return
nil
,
nil
,
err
C
}
// 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
{
...
...
vendor/github.com/xenolf/lego/acme/dns_challenge.go
View file @
8f583dcf
...
...
@@ -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 propagation
s
// 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
(
"
C
ould not determine the zone: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"
c
ould 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
(
"
C
ould not determine authoritative nameservers"
)
return
nil
,
fmt
.
Errorf
(
"
c
ould 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
(
"
U
nexpected response code '%s' for %s"
,
return
""
,
fmt
.
Errorf
(
"
u
nexpected 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
(
"
C
ould not find the start of authority"
)
return
""
,
fmt
.
Errorf
(
"
c
ould not find the start of authority"
)
}
// dnsMsgContainsCNAME checks for a CNAME answer in msg
...
...
vendor/github.com/xenolf/lego/acme/http.go
View file @
8f583dcf
...
...
@@ -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
(
"
F
ailed to marshal network message"
)
return
nil
,
errors
.
New
(
"
f
ailed 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
()
if
resp
.
StatusCode
>=
http
.
StatusBadRequest
{
return
resp
.
Header
,
err
}
err
:=
handleHTTPError
(
resp
)
func
postAsGet
(
j
*
jws
,
uri
string
,
respBody
interface
{})
(
*
http
.
Response
,
error
)
{
return
post
(
j
,
uri
,
[]
byte
{},
respBody
)
}
switch
err
.
(
type
)
{
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
)
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
,
err
P
:=
j
.
post
(
uri
,
reqBody
)
if
err
P
!=
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
)
}
vendor/github.com/xenolf/lego/acme/http_challenge_server.go
View file @
8f583dcf
...
...
@@ -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
(
"
C
ould not start HTTP server for challenge -> %v"
,
err
)
return
fmt
.
Errorf
(
"
c
ould 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
}
vendor/github.com/xenolf/lego/acme/tls_alpn_challenge.go
View file @
8f583dcf
...
...
@@ -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-0
1
#section-5.1
var
idPeAcmeIdentifierV1
=
asn1
.
ObjectIdentifier
{
1
,
3
,
6
,
1
,
5
,
5
,
7
,
1
,
3
0
,
1
}
// Reference: https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-0
5
#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-0
1
#section-3
// Reference: https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-0
5
#section-3
extensions
:=
[]
pkix
.
Extension
{
{
Id
:
idPeAcmeIdentifierV1
,
...
...
vendor/github.com/xenolf/lego/acme/tls_alpn_challenge_server.go
View file @
8f583dcf
...
...
@@ -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
...
...
vendor/github.com/xenolf/lego/acme/utils.go
View file @
8f583dcf
...
...
@@ -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
time
u
p
:=
time
.
After
(
timeout
)
time
U
p
:=
time
.
After
(
timeout
)
for
{
select
{
case
<-
time
u
p
:
return
fmt
.
Errorf
(
"
Time limit exceeded. L
ast error: %s"
,
lastErr
)
case
<-
time
U
p
:
return
fmt
.
Errorf
(
"
time limit exceeded: l
ast error: %s"
,
lastErr
)
default
:
}
...
...
vendor/manifest
View file @
8f583dcf
...
...
@@ -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
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment