summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/xenolf/lego/acme
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2016-11-16 19:28:52 -0500
committerGitHub <noreply@github.com>2016-11-16 19:28:52 -0500
commit0135904f7d3e1c0e763adaefe267c736616e3d26 (patch)
treec27be7588f98eaea62e0bd0c0087f2b348da9738 /vendor/github.com/xenolf/lego/acme
parent0b296dd8c2aefefe89787be5cc627d44cf431150 (diff)
downloadchat-0135904f7d3e1c0e763adaefe267c736616e3d26.tar.gz
chat-0135904f7d3e1c0e763adaefe267c736616e3d26.tar.bz2
chat-0135904f7d3e1c0e763adaefe267c736616e3d26.zip
Upgrading server dependancies (#4566)
Diffstat (limited to 'vendor/github.com/xenolf/lego/acme')
-rw-r--r--vendor/github.com/xenolf/lego/acme/client.go65
-rw-r--r--vendor/github.com/xenolf/lego/acme/crypto.go17
-rw-r--r--vendor/github.com/xenolf/lego/acme/crypto_test.go2
-rw-r--r--vendor/github.com/xenolf/lego/acme/dns_challenge.go27
-rw-r--r--vendor/github.com/xenolf/lego/acme/dns_challenge_test.go21
-rw-r--r--vendor/github.com/xenolf/lego/acme/http_challenge_server.go2
-rw-r--r--vendor/github.com/xenolf/lego/acme/http_challenge_test.go2
-rw-r--r--vendor/github.com/xenolf/lego/acme/messages.go8
-rw-r--r--vendor/github.com/xenolf/lego/acme/testdata/resolv.conf.15
-rw-r--r--vendor/github.com/xenolf/lego/acme/tls_sni_challenge_test.go2
10 files changed, 85 insertions, 66 deletions
diff --git a/vendor/github.com/xenolf/lego/acme/client.go b/vendor/github.com/xenolf/lego/acme/client.go
index 5eae8d26a..9f837af36 100644
--- a/vendor/github.com/xenolf/lego/acme/client.go
+++ b/vendor/github.com/xenolf/lego/acme/client.go
@@ -97,7 +97,7 @@ func NewClient(caDirURL string, user User, keyType KeyType) (*Client, error) {
return &Client{directory: dir, user: user, jws: jws, keyType: keyType, solvers: solvers}, nil
}
-// SetChallengeProvider specifies a custom provider that will make the solution available
+// SetChallengeProvider specifies a custom provider p that can solve the given challenge type.
func (c *Client) SetChallengeProvider(challenge Challenge, p ChallengeProvider) error {
switch challenge {
case HTTP01:
@@ -115,6 +115,9 @@ func (c *Client) SetChallengeProvider(challenge Challenge, p ChallengeProvider)
// SetHTTPAddress specifies a custom interface:port to be used for HTTP based challenges.
// If this option is not used, the default port 80 and all interfaces will be used.
// To only specify a port and no interface use the ":port" notation.
+//
+// NOTE: This REPLACES any custom HTTP provider previously set by calling
+// c.SetChallengeProvider with the default HTTP challenge provider.
func (c *Client) SetHTTPAddress(iface string) error {
host, port, err := net.SplitHostPort(iface)
if err != nil {
@@ -131,6 +134,9 @@ func (c *Client) SetHTTPAddress(iface string) error {
// SetTLSAddress specifies a custom interface:port to be used for TLS based challenges.
// If this option is not used, the default port 443 and all interfaces will be used.
// To only specify a port and no interface use the ":port" notation.
+//
+// NOTE: This REPLACES any custom TLS-SNI provider previously set by calling
+// c.SetChallengeProvider with the default TLS-SNI challenge provider.
func (c *Client) SetTLSAddress(iface string) error {
host, port, err := net.SplitHostPort(iface)
if err != nil {
@@ -347,7 +353,7 @@ DNSNames:
// your issued certificate as a bundle.
// This function will never return a partial certificate. If one domain in the list fails,
// the whole certificate will fail.
-func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto.PrivateKey) (CertificateResource, map[string]error) {
+func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto.PrivateKey, mustStaple bool) (CertificateResource, map[string]error) {
if bundle {
logf("[INFO][%s] acme: Obtaining bundled SAN certificate", strings.Join(domains, ", "))
} else {
@@ -368,7 +374,7 @@ func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto
logf("[INFO][%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
- cert, err := c.requestCertificate(challenges, bundle, privKey)
+ cert, err := c.requestCertificate(challenges, bundle, privKey, mustStaple)
if err != nil {
for _, chln := range challenges {
failures[chln.Domain] = err
@@ -404,7 +410,7 @@ func (c *Client) RevokeCertificate(certificate []byte) error {
// If bundle is true, the []byte contains both the issuer certificate and
// your issued certificate as a bundle.
// For private key reuse the PrivateKey property of the passed in CertificateResource should be non-nil.
-func (c *Client) RenewCertificate(cert CertificateResource, bundle bool) (CertificateResource, error) {
+func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple bool) (CertificateResource, error) {
// Input certificate is PEM encoded. Decode it here as we may need the decoded
// cert later on in the renewal process. The input may be a bundle or a single certificate.
certificates, err := parsePEMBundle(cert.Certificate)
@@ -421,50 +427,7 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle bool) (Certif
timeLeft := x509Cert.NotAfter.Sub(time.Now().UTC())
logf("[INFO][%s] acme: Trying renewal with %d hours remaining", cert.Domain, int(timeLeft.Hours()))
- // The first step of renewal is to check if we get a renewed cert
- // directly from the cert URL.
- resp, err := httpGet(cert.CertURL)
- if err != nil {
- return CertificateResource{}, err
- }
- defer resp.Body.Close()
- serverCertBytes, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return CertificateResource{}, err
- }
-
- serverCert, err := x509.ParseCertificate(serverCertBytes)
- if err != nil {
- return CertificateResource{}, err
- }
-
- // If the server responds with a different certificate we are effectively renewed.
- // TODO: Further test if we can actually use the new certificate (Our private key works)
- if !x509Cert.Equal(serverCert) {
- logf("[INFO][%s] acme: Server responded with renewed certificate", cert.Domain)
- issuedCert := pemEncode(derCertificateBytes(serverCertBytes))
- // If bundle is true, we want to return a certificate bundle.
- // To do this, we need the issuer certificate.
- if bundle {
- // The issuer certificate link is always supplied via an "up" link
- // in the response headers of a new certificate.
- links := parseLinks(resp.Header["Link"])
- issuerCert, err := c.getIssuerCertificate(links["up"])
- if err != nil {
- // If we fail to acquire the issuer cert, return the issued certificate - do not fail.
- logf("[ERROR][%s] acme: Could not bundle issuer certificate: %v", cert.Domain, err)
- } else {
- // Success - append the issuer cert to the issued cert.
- issuerCert = pemEncode(derCertificateBytes(issuerCert))
- issuedCert = append(issuedCert, issuerCert...)
- }
- }
-
- cert.Certificate = issuedCert
- return cert, nil
- }
-
- // If the certificate is the same, then we need to request a new certificate.
+ // We always need to request a new certificate to renew.
// 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 {
@@ -499,7 +462,7 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle bool) (Certif
domains = append(domains, x509Cert.Subject.CommonName)
}
- newCert, failures := c.ObtainCertificate(domains, bundle, privKey)
+ newCert, failures := c.ObtainCertificate(domains, bundle, privKey, mustStaple)
return newCert, failures[cert.Domain]
}
@@ -600,7 +563,7 @@ func (c *Client) getChallenges(domains []string) ([]authorizationResource, map[s
return challenges, failures
}
-func (c *Client) requestCertificate(authz []authorizationResource, bundle bool, privKey crypto.PrivateKey) (CertificateResource, error) {
+func (c *Client) requestCertificate(authz []authorizationResource, bundle bool, privKey crypto.PrivateKey, mustStaple bool) (CertificateResource, error) {
if len(authz) == 0 {
return CertificateResource{}, errors.New("Passed no authorizations to requestCertificate!")
}
@@ -621,7 +584,7 @@ func (c *Client) requestCertificate(authz []authorizationResource, bundle bool,
}
// TODO: should the CSR be customizable?
- csr, err := generateCsr(privKey, commonName.Domain, san)
+ csr, err := generateCsr(privKey, commonName.Domain, san, mustStaple)
if err != nil {
return CertificateResource{}, err
}
diff --git a/vendor/github.com/xenolf/lego/acme/crypto.go b/vendor/github.com/xenolf/lego/acme/crypto.go
index af97f5d1e..c63b23b99 100644
--- a/vendor/github.com/xenolf/lego/acme/crypto.go
+++ b/vendor/github.com/xenolf/lego/acme/crypto.go
@@ -20,6 +20,8 @@ import (
"strings"
"time"
+ "encoding/asn1"
+
"golang.org/x/crypto/ocsp"
)
@@ -47,6 +49,12 @@ const (
OCSPServerFailed = ocsp.ServerFailed
)
+// Constants for OCSP must staple
+var (
+ tlsFeatureExtensionOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 24}
+ ocspMustStapleFeature = []byte{0x30, 0x03, 0x02, 0x01, 0x05}
+)
+
// GetOCSPForCert takes a PEM encoded cert or cert bundle returning the raw OCSP response,
// the parsed response, and an error, if any. The returned []byte can be passed directly
// into the OCSPStaple property of a tls.Certificate. If the bundle only contains the
@@ -206,7 +214,7 @@ func generatePrivateKey(keyType KeyType) (crypto.PrivateKey, error) {
return nil, fmt.Errorf("Invalid KeyType: %s", keyType)
}
-func generateCsr(privateKey crypto.PrivateKey, domain string, san []string) ([]byte, error) {
+func generateCsr(privateKey crypto.PrivateKey, domain string, san []string, mustStaple bool) ([]byte, error) {
template := x509.CertificateRequest{
Subject: pkix.Name{
CommonName: domain,
@@ -217,6 +225,13 @@ func generateCsr(privateKey crypto.PrivateKey, domain string, san []string) ([]b
template.DNSNames = san
}
+ if mustStaple {
+ template.Extensions = append(template.Extensions, pkix.Extension{
+ Id: tlsFeatureExtensionOID,
+ Value: ocspMustStapleFeature,
+ })
+ }
+
return x509.CreateCertificateRequest(rand.Reader, &template, privateKey)
}
diff --git a/vendor/github.com/xenolf/lego/acme/crypto_test.go b/vendor/github.com/xenolf/lego/acme/crypto_test.go
index d2fc5088b..6f43835fb 100644
--- a/vendor/github.com/xenolf/lego/acme/crypto_test.go
+++ b/vendor/github.com/xenolf/lego/acme/crypto_test.go
@@ -24,7 +24,7 @@ func TestGenerateCSR(t *testing.T) {
t.Fatal("Error generating private key:", err)
}
- csr, err := generateCsr(key, "fizz.buzz", nil)
+ csr, err := generateCsr(key, "fizz.buzz", nil, true)
if err != nil {
t.Error("Error generating CSR:", err)
}
diff --git a/vendor/github.com/xenolf/lego/acme/dns_challenge.go b/vendor/github.com/xenolf/lego/acme/dns_challenge.go
index c5fd354a1..30f2170ff 100644
--- a/vendor/github.com/xenolf/lego/acme/dns_challenge.go
+++ b/vendor/github.com/xenolf/lego/acme/dns_challenge.go
@@ -23,14 +23,37 @@ var (
fqdnToZone = map[string]string{}
)
-var RecursiveNameservers = []string{
+const defaultResolvConf = "/etc/resolv.conf"
+
+var defaultNameservers = []string{
"google-public-dns-a.google.com:53",
"google-public-dns-b.google.com:53",
}
+var RecursiveNameservers = getNameservers(defaultResolvConf, defaultNameservers)
+
// DNSTimeout is used to override the default DNS timeout of 10 seconds.
var DNSTimeout = 10 * time.Second
+// getNameservers attempts to get systems nameservers before falling back to the defaults
+func getNameservers(path string, defaults []string) []string {
+ config, err := dns.ClientConfigFromFile(path)
+ if err != nil || len(config.Servers) == 0 {
+ return defaults
+ }
+
+ systemNameservers := []string{}
+ for _, server := range config.Servers {
+ // ensure all servers have a port number
+ if _, _, err := net.SplitHostPort(server); err != nil {
+ systemNameservers = append(systemNameservers, net.JoinHostPort(server, "53"))
+ } else {
+ systemNameservers = append(systemNameservers, server)
+ }
+ }
+ return systemNameservers
+}
+
// DNS01Record returns a DNS record which will fulfill the `dns-01` challenge
func DNS01Record(domain, keyAuth string) (fqdn string, value string, ttl int) {
keyAuthShaBytes := sha256.Sum256([]byte(keyAuth))
@@ -75,7 +98,7 @@ func (s *dnsChallenge) Solve(chlng challenge, domain string) error {
fqdn, value, _ := DNS01Record(domain, keyAuth)
- logf("[INFO][%s] Checking DNS record propagation...", domain)
+ logf("[INFO][%s] Checking DNS record propagation using %+v", domain, RecursiveNameservers)
var timeout, interval time.Duration
switch provider := s.provider.(type) {
diff --git a/vendor/github.com/xenolf/lego/acme/dns_challenge_test.go b/vendor/github.com/xenolf/lego/acme/dns_challenge_test.go
index 6e448854b..597aaac17 100644
--- a/vendor/github.com/xenolf/lego/acme/dns_challenge_test.go
+++ b/vendor/github.com/xenolf/lego/acme/dns_challenge_test.go
@@ -85,6 +85,15 @@ var checkAuthoritativeNssTestsErr = []struct {
},
}
+var checkResolvConfServersTests = []struct {
+ fixture string
+ expected []string
+ defaults []string
+}{
+ {"testdata/resolv.conf.1", []string{"10.200.3.249:53", "10.200.3.250:5353", "[2001:4860:4860::8844]:53", "[10.0.0.1]:5353"}, []string{"127.0.0.1:53"}},
+ {"testdata/resolv.conf.nonexistant", []string{"127.0.0.1:53"}, []string{"127.0.0.1:53"}},
+}
+
func TestDNSValidServerResponse(t *testing.T) {
PreCheckDNS = func(fqdn, value string) (bool, error) {
return true, nil
@@ -183,3 +192,15 @@ func TestCheckAuthoritativeNssErr(t *testing.T) {
}
}
}
+
+func TestResolveConfServers(t *testing.T) {
+ for _, tt := range checkResolvConfServersTests {
+ result := getNameservers(tt.fixture, tt.defaults)
+
+ sort.Strings(result)
+ sort.Strings(tt.expected)
+ if !reflect.DeepEqual(result, tt.expected) {
+ t.Errorf("#%s: expected %q; got %q", tt.fixture, tt.expected, result)
+ }
+ }
+}
diff --git a/vendor/github.com/xenolf/lego/acme/http_challenge_server.go b/vendor/github.com/xenolf/lego/acme/http_challenge_server.go
index 42541380c..64c6a8280 100644
--- a/vendor/github.com/xenolf/lego/acme/http_challenge_server.go
+++ b/vendor/github.com/xenolf/lego/acme/http_challenge_server.go
@@ -63,7 +63,7 @@ func (s *HTTPProviderServer) serve(domain, token, keyAuth string) {
w.Write([]byte(keyAuth))
logf("[INFO][%s] Served key authentication", domain)
} else {
- logf("[INFO] Received request for domain %s with method %s", r.Host, r.Method)
+ logf("[WARN] 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"))
}
})
diff --git a/vendor/github.com/xenolf/lego/acme/http_challenge_test.go b/vendor/github.com/xenolf/lego/acme/http_challenge_test.go
index fdd8f4d27..7400f56d4 100644
--- a/vendor/github.com/xenolf/lego/acme/http_challenge_test.go
+++ b/vendor/github.com/xenolf/lego/acme/http_challenge_test.go
@@ -51,7 +51,7 @@ func TestHTTPChallengeInvalidPort(t *testing.T) {
if err := solver.Solve(clientChallenge, "localhost:123456"); err == nil {
t.Errorf("Solve error: got %v, want error", err)
- } else if want := "invalid port 123456"; !strings.HasSuffix(err.Error(), want) {
+ } else if want, want18 := "invalid port 123456", "123456: invalid port"; !strings.HasSuffix(err.Error(), want) && !strings.HasSuffix(err.Error(), want18) {
t.Errorf("Solve error: got %q, want suffix %q", err.Error(), want)
}
}
diff --git a/vendor/github.com/xenolf/lego/acme/messages.go b/vendor/github.com/xenolf/lego/acme/messages.go
index 0efeae674..0f6514c3f 100644
--- a/vendor/github.com/xenolf/lego/acme/messages.go
+++ b/vendor/github.com/xenolf/lego/acme/messages.go
@@ -13,17 +13,10 @@ type directory struct {
RevokeCertURL string `json:"revoke-cert"`
}
-type recoveryKeyMessage struct {
- Length int `json:"length,omitempty"`
- Client jose.JsonWebKey `json:"client,omitempty"`
- Server jose.JsonWebKey `json:"client,omitempty"`
-}
-
type registrationMessage struct {
Resource string `json:"resource"`
Contact []string `json:"contact"`
Delete bool `json:"delete,omitempty"`
- // RecoveryKey recoveryKeyMessage `json:"recoveryKey,omitempty"`
}
// Registration is returned by the ACME server after the registration
@@ -36,7 +29,6 @@ type Registration struct {
Agreement string `json:"agreement,omitempty"`
Authorizations string `json:"authorizations,omitempty"`
Certificates string `json:"certificates,omitempty"`
- // RecoveryKey recoveryKeyMessage `json:"recoveryKey,omitempty"`
}
// RegistrationResource represents all important informations about a registration
diff --git a/vendor/github.com/xenolf/lego/acme/testdata/resolv.conf.1 b/vendor/github.com/xenolf/lego/acme/testdata/resolv.conf.1
new file mode 100644
index 000000000..3098f99b5
--- /dev/null
+++ b/vendor/github.com/xenolf/lego/acme/testdata/resolv.conf.1
@@ -0,0 +1,5 @@
+domain company.com
+nameserver 10.200.3.249
+nameserver 10.200.3.250:5353
+nameserver 2001:4860:4860::8844
+nameserver [10.0.0.1]:5353
diff --git a/vendor/github.com/xenolf/lego/acme/tls_sni_challenge_test.go b/vendor/github.com/xenolf/lego/acme/tls_sni_challenge_test.go
index 3aec74565..83b2833a9 100644
--- a/vendor/github.com/xenolf/lego/acme/tls_sni_challenge_test.go
+++ b/vendor/github.com/xenolf/lego/acme/tls_sni_challenge_test.go
@@ -59,7 +59,7 @@ func TestTLSSNIChallengeInvalidPort(t *testing.T) {
if err := solver.Solve(clientChallenge, "localhost:123456"); err == nil {
t.Errorf("Solve error: got %v, want error", err)
- } else if want := "invalid port 123456"; !strings.HasSuffix(err.Error(), want) {
+ } else if want, want18 := "invalid port 123456", "123456: invalid port"; !strings.HasSuffix(err.Error(), want) && !strings.HasSuffix(err.Error(), want18) {
t.Errorf("Solve error: got %q, want suffix %q", err.Error(), want)
}
}