summaryrefslogtreecommitdiff
path: root/cmd/ponzu/vendor/golang.org/x/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/ponzu/vendor/golang.org/x/crypto')
-rw-r--r--cmd/ponzu/vendor/golang.org/x/crypto/autocert/autocert.go973
-rw-r--r--cmd/ponzu/vendor/golang.org/x/crypto/autocert/autocert_test.go757
-rw-r--r--cmd/ponzu/vendor/golang.org/x/crypto/autocert/cache.go130
-rw-r--r--cmd/ponzu/vendor/golang.org/x/crypto/autocert/cache_test.go58
-rw-r--r--cmd/ponzu/vendor/golang.org/x/crypto/autocert/example_test.go36
-rw-r--r--cmd/ponzu/vendor/golang.org/x/crypto/autocert/listener.go160
-rw-r--r--cmd/ponzu/vendor/golang.org/x/crypto/autocert/renewal.go124
-rw-r--r--cmd/ponzu/vendor/golang.org/x/crypto/autocert/renewal_test.go191
-rw-r--r--cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/base64.go35
-rw-r--r--cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt.go294
-rw-r--r--cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go226
11 files changed, 0 insertions, 2984 deletions
diff --git a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/autocert.go b/cmd/ponzu/vendor/golang.org/x/crypto/autocert/autocert.go
deleted file mode 100644
index 453e722..0000000
--- a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/autocert.go
+++ /dev/null
@@ -1,973 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package autocert provides automatic access to certificates from Let's Encrypt
-// and any other ACME-based CA.
-//
-// This package is a work in progress and makes no API stability promises.
-package autocert
-
-import (
- "bytes"
- "context"
- "crypto"
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rand"
- "crypto/rsa"
- "crypto/tls"
- "crypto/x509"
- "crypto/x509/pkix"
- "encoding/pem"
- "errors"
- "fmt"
- "io"
- mathrand "math/rand"
- "net"
- "net/http"
- "path"
- "strconv"
- "strings"
- "sync"
- "time"
-
- "golang.org/x/crypto/acme"
-)
-
-// createCertRetryAfter is how much time to wait before removing a failed state
-// entry due to an unsuccessful createCert call.
-// This is a variable instead of a const for testing.
-// TODO: Consider making it configurable or an exp backoff?
-var createCertRetryAfter = time.Minute
-
-// pseudoRand is safe for concurrent use.
-var pseudoRand *lockedMathRand
-
-func init() {
- src := mathrand.NewSource(timeNow().UnixNano())
- pseudoRand = &lockedMathRand{rnd: mathrand.New(src)}
-}
-
-// AcceptTOS is a Manager.Prompt function that always returns true to
-// indicate acceptance of the CA's Terms of Service during account
-// registration.
-func AcceptTOS(tosURL string) bool { return true }
-
-// HostPolicy specifies which host names the Manager is allowed to respond to.
-// It returns a non-nil error if the host should be rejected.
-// The returned error is accessible via tls.Conn.Handshake and its callers.
-// See Manager's HostPolicy field and GetCertificate method docs for more details.
-type HostPolicy func(ctx context.Context, host string) error
-
-// HostWhitelist returns a policy where only the specified host names are allowed.
-// Only exact matches are currently supported. Subdomains, regexp or wildcard
-// will not match.
-func HostWhitelist(hosts ...string) HostPolicy {
- whitelist := make(map[string]bool, len(hosts))
- for _, h := range hosts {
- whitelist[h] = true
- }
- return func(_ context.Context, host string) error {
- if !whitelist[host] {
- return errors.New("acme/autocert: host not configured")
- }
- return nil
- }
-}
-
-// defaultHostPolicy is used when Manager.HostPolicy is not set.
-func defaultHostPolicy(context.Context, string) error {
- return nil
-}
-
-// Manager is a stateful certificate manager built on top of acme.Client.
-// It obtains and refreshes certificates automatically using "tls-sni-01",
-// "tls-sni-02" and "http-01" challenge types, as well as providing them
-// to a TLS server via tls.Config.
-//
-// You must specify a cache implementation, such as DirCache,
-// to reuse obtained certificates across program restarts.
-// Otherwise your server is very likely to exceed the certificate
-// issuer's request rate limits.
-type Manager struct {
- // Prompt specifies a callback function to conditionally accept a CA's Terms of Service (TOS).
- // The registration may require the caller to agree to the CA's TOS.
- // If so, Manager calls Prompt with a TOS URL provided by the CA. Prompt should report
- // whether the caller agrees to the terms.
- //
- // To always accept the terms, the callers can use AcceptTOS.
- Prompt func(tosURL string) bool
-
- // Cache optionally stores and retrieves previously-obtained certificates.
- // If nil, certs will only be cached for the lifetime of the Manager.
- //
- // Manager passes the Cache certificates data encoded in PEM, with private/public
- // parts combined in a single Cache.Put call, private key first.
- Cache Cache
-
- // HostPolicy controls which domains the Manager will attempt
- // to retrieve new certificates for. It does not affect cached certs.
- //
- // If non-nil, HostPolicy is called before requesting a new cert.
- // If nil, all hosts are currently allowed. This is not recommended,
- // as it opens a potential attack where clients connect to a server
- // by IP address and pretend to be asking for an incorrect host name.
- // Manager will attempt to obtain a certificate for that host, incorrectly,
- // eventually reaching the CA's rate limit for certificate requests
- // and making it impossible to obtain actual certificates.
- //
- // See GetCertificate for more details.
- HostPolicy HostPolicy
-
- // RenewBefore optionally specifies how early certificates should
- // be renewed before they expire.
- //
- // If zero, they're renewed 30 days before expiration.
- RenewBefore time.Duration
-
- // Client is used to perform low-level operations, such as account registration
- // and requesting new certificates.
- // If Client is nil, a zero-value acme.Client is used with acme.LetsEncryptURL
- // directory endpoint and a newly-generated ECDSA P-256 key.
- //
- // Mutating the field after the first call of GetCertificate method will have no effect.
- Client *acme.Client
-
- // Email optionally specifies a contact email address.
- // This is used by CAs, such as Let's Encrypt, to notify about problems
- // with issued certificates.
- //
- // If the Client's account key is already registered, Email is not used.
- Email string
-
- // ForceRSA makes the Manager generate certificates with 2048-bit RSA keys.
- //
- // If false, a default is used. Currently the default
- // is EC-based keys using the P-256 curve.
- ForceRSA bool
-
- clientMu sync.Mutex
- client *acme.Client // initialized by acmeClient method
-
- stateMu sync.Mutex
- state map[string]*certState // keyed by domain name
-
- // renewal tracks the set of domains currently running renewal timers.
- // It is keyed by domain name.
- renewalMu sync.Mutex
- renewal map[string]*domainRenewal
-
- // tokensMu guards the rest of the fields: tryHTTP01, certTokens and httpTokens.
- tokensMu sync.RWMutex
- // tryHTTP01 indicates whether the Manager should try "http-01" challenge type
- // during the authorization flow.
- tryHTTP01 bool
- // httpTokens contains response body values for http-01 challenges
- // and is keyed by the URL path at which a challenge response is expected
- // to be provisioned.
- // The entries are stored for the duration of the authorization flow.
- httpTokens map[string][]byte
- // certTokens contains temporary certificates for tls-sni challenges
- // and is keyed by token domain name, which matches server name of ClientHello.
- // Keys always have ".acme.invalid" suffix.
- // The entries are stored for the duration of the authorization flow.
- certTokens map[string]*tls.Certificate
-}
-
-// GetCertificate implements the tls.Config.GetCertificate hook.
-// It provides a TLS certificate for hello.ServerName host, including answering
-// *.acme.invalid (TLS-SNI) challenges. All other fields of hello are ignored.
-//
-// If m.HostPolicy is non-nil, GetCertificate calls the policy before requesting
-// a new cert. A non-nil error returned from m.HostPolicy halts TLS negotiation.
-// The error is propagated back to the caller of GetCertificate and is user-visible.
-// This does not affect cached certs. See HostPolicy field description for more details.
-func (m *Manager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
- if m.Prompt == nil {
- return nil, errors.New("acme/autocert: Manager.Prompt not set")
- }
-
- name := hello.ServerName
- if name == "" {
- return nil, errors.New("acme/autocert: missing server name")
- }
- if !strings.Contains(strings.Trim(name, "."), ".") {
- return nil, errors.New("acme/autocert: server name component count invalid")
- }
- if strings.ContainsAny(name, `/\`) {
- return nil, errors.New("acme/autocert: server name contains invalid character")
- }
-
- // In the worst-case scenario, the timeout needs to account for caching, host policy,
- // domain ownership verification and certificate issuance.
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
- defer cancel()
-
- // check whether this is a token cert requested for TLS-SNI challenge
- if strings.HasSuffix(name, ".acme.invalid") {
- m.tokensMu.RLock()
- defer m.tokensMu.RUnlock()
- if cert := m.certTokens[name]; cert != nil {
- return cert, nil
- }
- if cert, err := m.cacheGet(ctx, name); err == nil {
- return cert, nil
- }
- // TODO: cache error results?
- return nil, fmt.Errorf("acme/autocert: no token cert for %q", name)
- }
-
- // regular domain
- name = strings.TrimSuffix(name, ".") // golang.org/issue/18114
- cert, err := m.cert(ctx, name)
- if err == nil {
- return cert, nil
- }
- if err != ErrCacheMiss {
- return nil, err
- }
-
- // first-time
- if err := m.hostPolicy()(ctx, name); err != nil {
- return nil, err
- }
- cert, err = m.createCert(ctx, name)
- if err != nil {
- return nil, err
- }
- m.cachePut(ctx, name, cert)
- return cert, nil
-}
-
-// HTTPHandler configures the Manager to provision ACME "http-01" challenge responses.
-// It returns an http.Handler that responds to the challenges and must be
-// running on port 80. If it receives a request that is not an ACME challenge,
-// it delegates the request to the optional fallback handler.
-//
-// If fallback is nil, the returned handler redirects all GET and HEAD requests
-// to the default TLS port 443 with 302 Found status code, preserving the original
-// request path and query. It responds with 400 Bad Request to all other HTTP methods.
-// The fallback is not protected by the optional HostPolicy.
-//
-// Because the fallback handler is run with unencrypted port 80 requests,
-// the fallback should not serve TLS-only requests.
-//
-// If HTTPHandler is never called, the Manager will only use TLS SNI
-// challenges for domain verification.
-func (m *Manager) HTTPHandler(fallback http.Handler) http.Handler {
- m.tokensMu.Lock()
- defer m.tokensMu.Unlock()
- m.tryHTTP01 = true
-
- if fallback == nil {
- fallback = http.HandlerFunc(handleHTTPRedirect)
- }
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- if !strings.HasPrefix(r.URL.Path, "/.well-known/acme-challenge/") {
- fallback.ServeHTTP(w, r)
- return
- }
- // A reasonable context timeout for cache and host policy only,
- // because we don't wait for a new certificate issuance here.
- ctx, cancel := context.WithTimeout(r.Context(), time.Minute)
- defer cancel()
- if err := m.hostPolicy()(ctx, r.Host); err != nil {
- http.Error(w, err.Error(), http.StatusForbidden)
- return
- }
- data, err := m.httpToken(ctx, r.URL.Path)
- if err != nil {
- http.Error(w, err.Error(), http.StatusNotFound)
- return
- }
- w.Write(data)
- })
-}
-
-func handleHTTPRedirect(w http.ResponseWriter, r *http.Request) {
- if r.Method != "GET" && r.Method != "HEAD" {
- http.Error(w, "Use HTTPS", http.StatusBadRequest)
- return
- }
- target := "https://" + stripPort(r.Host) + r.URL.RequestURI()
- http.Redirect(w, r, target, http.StatusFound)
-}
-
-func stripPort(hostport string) string {
- host, _, err := net.SplitHostPort(hostport)
- if err != nil {
- return hostport
- }
- return net.JoinHostPort(host, "443")
-}
-
-// cert returns an existing certificate either from m.state or cache.
-// If a certificate is found in cache but not in m.state, the latter will be filled
-// with the cached value.
-func (m *Manager) cert(ctx context.Context, name string) (*tls.Certificate, error) {
- m.stateMu.Lock()
- if s, ok := m.state[name]; ok {
- m.stateMu.Unlock()
- s.RLock()
- defer s.RUnlock()
- return s.tlscert()
- }
- defer m.stateMu.Unlock()
- cert, err := m.cacheGet(ctx, name)
- if err != nil {
- return nil, err
- }
- signer, ok := cert.PrivateKey.(crypto.Signer)
- if !ok {
- return nil, errors.New("acme/autocert: private key cannot sign")
- }
- if m.state == nil {
- m.state = make(map[string]*certState)
- }
- s := &certState{
- key: signer,
- cert: cert.Certificate,
- leaf: cert.Leaf,
- }
- m.state[name] = s
- go m.renew(name, s.key, s.leaf.NotAfter)
- return cert, nil
-}
-
-// cacheGet always returns a valid certificate, or an error otherwise.
-// If a cached certficate exists but is not valid, ErrCacheMiss is returned.
-func (m *Manager) cacheGet(ctx context.Context, domain string) (*tls.Certificate, error) {
- if m.Cache == nil {
- return nil, ErrCacheMiss
- }
- data, err := m.Cache.Get(ctx, domain)
- if err != nil {
- return nil, err
- }
-
- // private
- priv, pub := pem.Decode(data)
- if priv == nil || !strings.Contains(priv.Type, "PRIVATE") {
- return nil, ErrCacheMiss
- }
- privKey, err := parsePrivateKey(priv.Bytes)
- if err != nil {
- return nil, err
- }
-
- // public
- var pubDER [][]byte
- for len(pub) > 0 {
- var b *pem.Block
- b, pub = pem.Decode(pub)
- if b == nil {
- break
- }
- pubDER = append(pubDER, b.Bytes)
- }
- if len(pub) > 0 {
- // Leftover content not consumed by pem.Decode. Corrupt. Ignore.
- return nil, ErrCacheMiss
- }
-
- // verify and create TLS cert
- leaf, err := validCert(domain, pubDER, privKey)
- if err != nil {
- return nil, ErrCacheMiss
- }
- tlscert := &tls.Certificate{
- Certificate: pubDER,
- PrivateKey: privKey,
- Leaf: leaf,
- }
- return tlscert, nil
-}
-
-func (m *Manager) cachePut(ctx context.Context, domain string, tlscert *tls.Certificate) error {
- if m.Cache == nil {
- return nil
- }
-
- // contains PEM-encoded data
- var buf bytes.Buffer
-
- // private
- switch key := tlscert.PrivateKey.(type) {
- case *ecdsa.PrivateKey:
- if err := encodeECDSAKey(&buf, key); err != nil {
- return err
- }
- case *rsa.PrivateKey:
- b := x509.MarshalPKCS1PrivateKey(key)
- pb := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: b}
- if err := pem.Encode(&buf, pb); err != nil {
- return err
- }
- default:
- return errors.New("acme/autocert: unknown private key type")
- }
-
- // public
- for _, b := range tlscert.Certificate {
- pb := &pem.Block{Type: "CERTIFICATE", Bytes: b}
- if err := pem.Encode(&buf, pb); err != nil {
- return err
- }
- }
-
- return m.Cache.Put(ctx, domain, buf.Bytes())
-}
-
-func encodeECDSAKey(w io.Writer, key *ecdsa.PrivateKey) error {
- b, err := x509.MarshalECPrivateKey(key)
- if err != nil {
- return err
- }
- pb := &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
- return pem.Encode(w, pb)
-}
-
-// createCert starts the domain ownership verification and returns a certificate
-// for that domain upon success.
-//
-// If the domain is already being verified, it waits for the existing verification to complete.
-// Either way, createCert blocks for the duration of the whole process.
-func (m *Manager) createCert(ctx context.Context, domain string) (*tls.Certificate, error) {
- // TODO: maybe rewrite this whole piece using sync.Once
- state, err := m.certState(domain)
- if err != nil {
- return nil, err
- }
- // state may exist if another goroutine is already working on it
- // in which case just wait for it to finish
- if !state.locked {
- state.RLock()
- defer state.RUnlock()
- return state.tlscert()
- }
-
- // We are the first; state is locked.
- // Unblock the readers when domain ownership is verified
- // and we got the cert or the process failed.
- defer state.Unlock()
- state.locked = false
-
- der, leaf, err := m.authorizedCert(ctx, state.key, domain)
- if err != nil {
- // Remove the failed state after some time,
- // making the manager call createCert again on the following TLS hello.
- time.AfterFunc(createCertRetryAfter, func() {
- defer testDidRemoveState(domain)
- m.stateMu.Lock()
- defer m.stateMu.Unlock()
- // Verify the state hasn't changed and it's still invalid
- // before deleting.
- s, ok := m.state[domain]
- if !ok {
- return
- }
- if _, err := validCert(domain, s.cert, s.key); err == nil {
- return
- }
- delete(m.state, domain)
- })
- return nil, err
- }
- state.cert = der
- state.leaf = leaf
- go m.renew(domain, state.key, state.leaf.NotAfter)
- return state.tlscert()
-}
-
-// certState returns a new or existing certState.
-// If a new certState is returned, state.exist is false and the state is locked.
-// The returned error is non-nil only in the case where a new state could not be created.
-func (m *Manager) certState(domain string) (*certState, error) {
- m.stateMu.Lock()
- defer m.stateMu.Unlock()
- if m.state == nil {
- m.state = make(map[string]*certState)
- }
- // existing state
- if state, ok := m.state[domain]; ok {
- return state, nil
- }
-
- // new locked state
- var (
- err error
- key crypto.Signer
- )
- if m.ForceRSA {
- key, err = rsa.GenerateKey(rand.Reader, 2048)
- } else {
- key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- }
- if err != nil {
- return nil, err
- }
-
- state := &certState{
- key: key,
- locked: true,
- }
- state.Lock() // will be unlocked by m.certState caller
- m.state[domain] = state
- return state, nil
-}
-
-// authorizedCert starts the domain ownership verification process and requests a new cert upon success.
-// The key argument is the certificate private key.
-func (m *Manager) authorizedCert(ctx context.Context, key crypto.Signer, domain string) (der [][]byte, leaf *x509.Certificate, err error) {
- client, err := m.acmeClient(ctx)
- if err != nil {
- return nil, nil, err
- }
-
- if err := m.verify(ctx, client, domain); err != nil {
- return nil, nil, err
- }
- csr, err := certRequest(key, domain)
- if err != nil {
- return nil, nil, err
- }
- der, _, err = client.CreateCert(ctx, csr, 0, true)
- if err != nil {
- return nil, nil, err
- }
- leaf, err = validCert(domain, der, key)
- if err != nil {
- return nil, nil, err
- }
- return der, leaf, nil
-}
-
-// verify runs the identifier (domain) authorization flow
-// using each applicable ACME challenge type.
-func (m *Manager) verify(ctx context.Context, client *acme.Client, domain string) error {
- // The list of challenge types we'll try to fulfill
- // in this specific order.
- challengeTypes := []string{"tls-sni-02", "tls-sni-01"}
- m.tokensMu.RLock()
- if m.tryHTTP01 {
- challengeTypes = append(challengeTypes, "http-01")
- }
- m.tokensMu.RUnlock()
-
- var nextTyp int // challengeType index of the next challenge type to try
- for {
- // Start domain authorization and get the challenge.
- authz, err := client.Authorize(ctx, domain)
- if err != nil {
- return err
- }
- // No point in accepting challenges if the authorization status
- // is in a final state.
- switch authz.Status {
- case acme.StatusValid:
- return nil // already authorized
- case acme.StatusInvalid:
- return fmt.Errorf("acme/autocert: invalid authorization %q", authz.URI)
- }
-
- // Pick the next preferred challenge.
- var chal *acme.Challenge
- for chal == nil && nextTyp < len(challengeTypes) {
- chal = pickChallenge(challengeTypes[nextTyp], authz.Challenges)
- nextTyp++
- }
- if chal == nil {
- return fmt.Errorf("acme/autocert: unable to authorize %q; tried %q", domain, challengeTypes)
- }
- cleanup, err := m.fulfill(ctx, client, chal)
- if err != nil {
- continue
- }
- defer cleanup()
- if _, err := client.Accept(ctx, chal); err != nil {
- continue
- }
-
- // A challenge is fulfilled and accepted: wait for the CA to validate.
- if _, err := client.WaitAuthorization(ctx, authz.URI); err == nil {
- return nil
- }
- }
-}
-
-// fulfill provisions a response to the challenge chal.
-// The cleanup is non-nil only if provisioning succeeded.
-func (m *Manager) fulfill(ctx context.Context, client *acme.Client, chal *acme.Challenge) (cleanup func(), err error) {
- switch chal.Type {
- case "tls-sni-01":
- cert, name, err := client.TLSSNI01ChallengeCert(chal.Token)
- if err != nil {
- return nil, err
- }
- m.putCertToken(ctx, name, &cert)
- return func() { go m.deleteCertToken(name) }, nil
- case "tls-sni-02":
- cert, name, err := client.TLSSNI02ChallengeCert(chal.Token)
- if err != nil {
- return nil, err
- }
- m.putCertToken(ctx, name, &cert)
- return func() { go m.deleteCertToken(name) }, nil
- case "http-01":
- resp, err := client.HTTP01ChallengeResponse(chal.Token)
- if err != nil {
- return nil, err
- }
- p := client.HTTP01ChallengePath(chal.Token)
- m.putHTTPToken(ctx, p, resp)
- return func() { go m.deleteHTTPToken(p) }, nil
- }
- return nil, fmt.Errorf("acme/autocert: unknown challenge type %q", chal.Type)
-}
-
-func pickChallenge(typ string, chal []*acme.Challenge) *acme.Challenge {
- for _, c := range chal {
- if c.Type == typ {
- return c
- }
- }
- return nil
-}
-
-// putCertToken stores the cert under the named key in both m.certTokens map
-// and m.Cache.
-func (m *Manager) putCertToken(ctx context.Context, name string, cert *tls.Certificate) {
- m.tokensMu.Lock()
- defer m.tokensMu.Unlock()
- if m.certTokens == nil {
- m.certTokens = make(map[string]*tls.Certificate)
- }
- m.certTokens[name] = cert
- m.cachePut(ctx, name, cert)
-}
-
-// deleteCertToken removes the token certificate for the specified domain name
-// from both m.certTokens map and m.Cache.
-func (m *Manager) deleteCertToken(name string) {
- m.tokensMu.Lock()
- defer m.tokensMu.Unlock()
- delete(m.certTokens, name)
- if m.Cache != nil {
- m.Cache.Delete(context.Background(), name)
- }
-}
-
-// httpToken retrieves an existing http-01 token value from an in-memory map
-// or the optional cache.
-func (m *Manager) httpToken(ctx context.Context, tokenPath string) ([]byte, error) {
- m.tokensMu.RLock()
- defer m.tokensMu.RUnlock()
- if v, ok := m.httpTokens[tokenPath]; ok {
- return v, nil
- }
- if m.Cache == nil {
- return nil, fmt.Errorf("acme/autocert: no token at %q", tokenPath)
- }
- return m.Cache.Get(ctx, httpTokenCacheKey(tokenPath))
-}
-
-// putHTTPToken stores an http-01 token value using tokenPath as key
-// in both in-memory map and the optional Cache.
-//
-// It ignores any error returned from Cache.Put.
-func (m *Manager) putHTTPToken(ctx context.Context, tokenPath, val string) {
- m.tokensMu.Lock()
- defer m.tokensMu.Unlock()
- if m.httpTokens == nil {
- m.httpTokens = make(map[string][]byte)
- }
- b := []byte(val)
- m.httpTokens[tokenPath] = b
- if m.Cache != nil {
- m.Cache.Put(ctx, httpTokenCacheKey(tokenPath), b)
- }
-}
-
-// deleteHTTPToken removes an http-01 token value from both in-memory map
-// and the optional Cache, ignoring any error returned from the latter.
-//
-// If m.Cache is non-nil, it blocks until Cache.Delete returns without a timeout.
-func (m *Manager) deleteHTTPToken(tokenPath string) {
- m.tokensMu.Lock()
- defer m.tokensMu.Unlock()
- delete(m.httpTokens, tokenPath)
- if m.Cache != nil {
- m.Cache.Delete(context.Background(), httpTokenCacheKey(tokenPath))
- }
-}
-
-// httpTokenCacheKey returns a key at which an http-01 token value may be stored
-// in the Manager's optional Cache.
-func httpTokenCacheKey(tokenPath string) string {
- return "http-01-" + path.Base(tokenPath)
-}
-
-// renew starts a cert renewal timer loop, one per domain.
-//
-// The loop is scheduled in two cases:
-// - a cert was fetched from cache for the first time (wasn't in m.state)
-// - a new cert was created by m.createCert
-//
-// The key argument is a certificate private key.
-// The exp argument is the cert expiration time (NotAfter).
-func (m *Manager) renew(domain string, key crypto.Signer, exp time.Time) {
- m.renewalMu.Lock()
- defer m.renewalMu.Unlock()
- if m.renewal[domain] != nil {
- // another goroutine is already on it
- return
- }
- if m.renewal == nil {
- m.renewal = make(map[string]*domainRenewal)
- }
- dr := &domainRenewal{m: m, domain: domain, key: key}
- m.renewal[domain] = dr
- dr.start(exp)
-}
-
-// stopRenew stops all currently running cert renewal timers.
-// The timers are not restarted during the lifetime of the Manager.
-func (m *Manager) stopRenew() {
- m.renewalMu.Lock()
- defer m.renewalMu.Unlock()
- for name, dr := range m.renewal {
- delete(m.renewal, name)
- dr.stop()
- }
-}
-
-func (m *Manager) accountKey(ctx context.Context) (crypto.Signer, error) {
- const keyName = "acme_account.key"
-
- genKey := func() (*ecdsa.PrivateKey, error) {
- return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- }
-
- if m.Cache == nil {
- return genKey()
- }
-
- data, err := m.Cache.Get(ctx, keyName)
- if err == ErrCacheMiss {
- key, err := genKey()
- if err != nil {
- return nil, err
- }
- var buf bytes.Buffer
- if err := encodeECDSAKey(&buf, key); err != nil {
- return nil, err
- }
- if err := m.Cache.Put(ctx, keyName, buf.Bytes()); err != nil {
- return nil, err
- }
- return key, nil
- }
- if err != nil {
- return nil, err
- }
-
- priv, _ := pem.Decode(data)
- if priv == nil || !strings.Contains(priv.Type, "PRIVATE") {
- return nil, errors.New("acme/autocert: invalid account key found in cache")
- }
- return parsePrivateKey(priv.Bytes)
-}
-
-func (m *Manager) acmeClient(ctx context.Context) (*acme.Client, error) {
- m.clientMu.Lock()
- defer m.clientMu.Unlock()
- if m.client != nil {
- return m.client, nil
- }
-
- client := m.Client
- if client == nil {
- client = &acme.Client{DirectoryURL: acme.LetsEncryptURL}
- }
- if client.Key == nil {
- var err error
- client.Key, err = m.accountKey(ctx)
- if err != nil {
- return nil, err
- }
- }
- var contact []string
- if m.Email != "" {
- contact = []string{"mailto:" + m.Email}
- }
- a := &acme.Account{Contact: contact}
- _, err := client.Register(ctx, a, m.Prompt)
- if ae, ok := err.(*acme.Error); err == nil || ok && ae.StatusCode == http.StatusConflict {
- // conflict indicates the key is already registered
- m.client = client
- err = nil
- }
- return m.client, err
-}
-
-func (m *Manager) hostPolicy() HostPolicy {
- if m.HostPolicy != nil {
- return m.HostPolicy
- }
- return defaultHostPolicy
-}
-
-func (m *Manager) renewBefore() time.Duration {
- if m.RenewBefore > renewJitter {
- return m.RenewBefore
- }
- return 720 * time.Hour // 30 days
-}
-
-// certState is ready when its mutex is unlocked for reading.
-type certState struct {
- sync.RWMutex
- locked bool // locked for read/write
- key crypto.Signer // private key for cert
- cert [][]byte // DER encoding
- leaf *x509.Certificate // parsed cert[0]; always non-nil if cert != nil
-}
-
-// tlscert creates a tls.Certificate from s.key and s.cert.
-// Callers should wrap it in s.RLock() and s.RUnlock().
-func (s *certState) tlscert() (*tls.Certificate, error) {
- if s.key == nil {
- return nil, errors.New("acme/autocert: missing signer")
- }
- if len(s.cert) == 0 {
- return nil, errors.New("acme/autocert: missing certificate")
- }
- return &tls.Certificate{
- PrivateKey: s.key,
- Certificate: s.cert,
- Leaf: s.leaf,
- }, nil
-}
-
-// certRequest creates a certificate request for the given common name cn
-// and optional SANs.
-func certRequest(key crypto.Signer, cn string, san ...string) ([]byte, error) {
- req := &x509.CertificateRequest{
- Subject: pkix.Name{CommonName: cn},
- DNSNames: san,
- }
- return x509.CreateCertificateRequest(rand.Reader, req, key)
-}
-
-// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
-// PKCS#1 private keys by default, while OpenSSL 1.0.0 generates PKCS#8 keys.
-// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
-//
-// Inspired by parsePrivateKey in crypto/tls/tls.go.
-func parsePrivateKey(der []byte) (crypto.Signer, error) {
- if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
- return key, nil
- }
- if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
- switch key := key.(type) {
- case *rsa.PrivateKey:
- return key, nil
- case *ecdsa.PrivateKey:
- return key, nil
- default:
- return nil, errors.New("acme/autocert: unknown private key type in PKCS#8 wrapping")
- }
- }
- if key, err := x509.ParseECPrivateKey(der); err == nil {
- return key, nil
- }
-
- return nil, errors.New("acme/autocert: failed to parse private key")
-}
-
-// validCert parses a cert chain provided as der argument and verifies the leaf, der[0],
-// corresponds to the private key, as well as the domain match and expiration dates.
-// It doesn't do any revocation checking.
-//
-// The returned value is the verified leaf cert.
-func validCert(domain string, der [][]byte, key crypto.Signer) (leaf *x509.Certificate, err error) {
- // parse public part(s)
- var n int
- for _, b := range der {
- n += len(b)
- }
- pub := make([]byte, n)
- n = 0
- for _, b := range der {
- n += copy(pub[n:], b)
- }
- x509Cert, err := x509.ParseCertificates(pub)
- if len(x509Cert) == 0 {
- return nil, errors.New("acme/autocert: no public key found")
- }
- // verify the leaf is not expired and matches the domain name
- leaf = x509Cert[0]
- now := timeNow()
- if now.Before(leaf.NotBefore) {
- return nil, errors.New("acme/autocert: certificate is not valid yet")
- }
- if now.After(leaf.NotAfter) {
- return nil, errors.New("acme/autocert: expired certificate")
- }
- if err := leaf.VerifyHostname(domain); err != nil {
- return nil, err
- }
- // ensure the leaf corresponds to the private key
- switch pub := leaf.PublicKey.(type) {
- case *rsa.PublicKey:
- prv, ok := key.(*rsa.PrivateKey)
- if !ok {
- return nil, errors.New("acme/autocert: private key type does not match public key type")
- }
- if pub.N.Cmp(prv.N) != 0 {
- return nil, errors.New("acme/autocert: private key does not match public key")
- }
- case *ecdsa.PublicKey:
- prv, ok := key.(*ecdsa.PrivateKey)
- if !ok {
- return nil, errors.New("acme/autocert: private key type does not match public key type")
- }
- if pub.X.Cmp(prv.X) != 0 || pub.Y.Cmp(prv.Y) != 0 {
- return nil, errors.New("acme/autocert: private key does not match public key")
- }
- default:
- return nil, errors.New("acme/autocert: unknown public key algorithm")
- }
- return leaf, nil
-}
-
-func retryAfter(v string) time.Duration {
- if i, err := strconv.Atoi(v); err == nil {
- return time.Duration(i) * time.Second
- }
- if t, err := http.ParseTime(v); err == nil {
- return t.Sub(timeNow())
- }
- return time.Second
-}
-
-type lockedMathRand struct {
- sync.Mutex
- rnd *mathrand.Rand
-}
-
-func (r *lockedMathRand) int63n(max int64) int64 {
- r.Lock()
- n := r.rnd.Int63n(max)
- r.Unlock()
- return n
-}
-
-// For easier testing.
-var (
- timeNow = time.Now
-
- // Called when a state is removed.
- testDidRemoveState = func(domain string) {}
-)
diff --git a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/autocert_test.go b/cmd/ponzu/vendor/golang.org/x/crypto/autocert/autocert_test.go
deleted file mode 100644
index 2da1912..0000000
--- a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/autocert_test.go
+++ /dev/null
@@ -1,757 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package autocert
-
-import (
- "context"
- "crypto"
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rand"
- "crypto/rsa"
- "crypto/tls"
- "crypto/x509"
- "crypto/x509/pkix"
- "encoding/base64"
- "encoding/json"
- "fmt"
- "html/template"
- "io"
- "math/big"
- "net/http"
- "net/http/httptest"
- "reflect"
- "strings"
- "sync"
- "testing"
- "time"
-
- "golang.org/x/crypto/acme"
-)
-
-var discoTmpl = template.Must(template.New("disco").Parse(`{
- "new-reg": "{{.}}/new-reg",
- "new-authz": "{{.}}/new-authz",
- "new-cert": "{{.}}/new-cert"
-}`))
-
-var authzTmpl = template.Must(template.New("authz").Parse(`{
- "status": "pending",
- "challenges": [
- {
- "uri": "{{.}}/challenge/1",
- "type": "tls-sni-01",
- "token": "token-01"
- },
- {
- "uri": "{{.}}/challenge/2",
- "type": "tls-sni-02",
- "token": "token-02"
- },
- {
- "uri": "{{.}}/challenge/dns-01",
- "type": "dns-01",
- "token": "token-dns-01"
- },
- {
- "uri": "{{.}}/challenge/http-01",
- "type": "http-01",
- "token": "token-http-01"
- }
- ]
-}`))
-
-type memCache struct {
- mu sync.Mutex
- keyData map[string][]byte
-}
-
-func (m *memCache) Get(ctx context.Context, key string) ([]byte, error) {
- m.mu.Lock()
- defer m.mu.Unlock()
-
- v, ok := m.keyData[key]
- if !ok {
- return nil, ErrCacheMiss
- }
- return v, nil
-}
-
-func (m *memCache) Put(ctx context.Context, key string, data []byte) error {
- m.mu.Lock()
- defer m.mu.Unlock()
-
- m.keyData[key] = data
- return nil
-}
-
-func (m *memCache) Delete(ctx context.Context, key string) error {
- m.mu.Lock()
- defer m.mu.Unlock()
-
- delete(m.keyData, key)
- return nil
-}
-
-func newMemCache() *memCache {
- return &memCache{
- keyData: make(map[string][]byte),
- }
-}
-
-func dummyCert(pub interface{}, san ...string) ([]byte, error) {
- return dateDummyCert(pub, time.Now(), time.Now().Add(90*24*time.Hour), san...)
-}
-
-func dateDummyCert(pub interface{}, start, end time.Time, san ...string) ([]byte, error) {
- // use EC key to run faster on 386
- key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- return nil, err
- }
- t := &x509.Certificate{
- SerialNumber: big.NewInt(1),
- NotBefore: start,
- NotAfter: end,
- BasicConstraintsValid: true,
- KeyUsage: x509.KeyUsageKeyEncipherment,
- DNSNames: san,
- }
- if pub == nil {
- pub = &key.PublicKey
- }
- return x509.CreateCertificate(rand.Reader, t, t, pub, key)
-}
-
-func decodePayload(v interface{}, r io.Reader) error {
- var req struct{ Payload string }
- if err := json.NewDecoder(r).Decode(&req); err != nil {
- return err
- }
- payload, err := base64.RawURLEncoding.DecodeString(req.Payload)
- if err != nil {
- return err
- }
- return json.Unmarshal(payload, v)
-}
-
-func TestGetCertificate(t *testing.T) {
- man := &Manager{Prompt: AcceptTOS}
- defer man.stopRenew()
- hello := &tls.ClientHelloInfo{ServerName: "example.org"}
- testGetCertificate(t, man, "example.org", hello)
-}
-
-func TestGetCertificate_trailingDot(t *testing.T) {
- man := &Manager{Prompt: AcceptTOS}
- defer man.stopRenew()
- hello := &tls.ClientHelloInfo{ServerName: "example.org."}
- testGetCertificate(t, man, "example.org", hello)
-}
-
-func TestGetCertificate_ForceRSA(t *testing.T) {
- man := &Manager{
- Prompt: AcceptTOS,
- Cache: newMemCache(),
- ForceRSA: true,
- }
- defer man.stopRenew()
- hello := &tls.ClientHelloInfo{ServerName: "example.org"}
- testGetCertificate(t, man, "example.org", hello)
-
- cert, err := man.cacheGet(context.Background(), "example.org")
- if err != nil {
- t.Fatalf("man.cacheGet: %v", err)
- }
- if _, ok := cert.PrivateKey.(*rsa.PrivateKey); !ok {
- t.Errorf("cert.PrivateKey is %T; want *rsa.PrivateKey", cert.PrivateKey)
- }
-}
-
-func TestGetCertificate_nilPrompt(t *testing.T) {
- man := &Manager{}
- defer man.stopRenew()
- url, finish := startACMEServerStub(t, man, "example.org")
- defer finish()
- key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- t.Fatal(err)
- }
- man.Client = &acme.Client{
- Key: key,
- DirectoryURL: url,
- }
- hello := &tls.ClientHelloInfo{ServerName: "example.org"}
- if _, err := man.GetCertificate(hello); err == nil {
- t.Error("got certificate for example.org; wanted error")
- }
-}
-
-func TestGetCertificate_expiredCache(t *testing.T) {
- // Make an expired cert and cache it.
- pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- t.Fatal(err)
- }
- tmpl := &x509.Certificate{
- SerialNumber: big.NewInt(1),
- Subject: pkix.Name{CommonName: "example.org"},
- NotAfter: time.Now(),
- }
- pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &pk.PublicKey, pk)
- if err != nil {
- t.Fatal(err)
- }
- tlscert := &tls.Certificate{
- Certificate: [][]byte{pub},
- PrivateKey: pk,
- }
-
- man := &Manager{Prompt: AcceptTOS, Cache: newMemCache()}
- defer man.stopRenew()
- if err := man.cachePut(context.Background(), "example.org", tlscert); err != nil {
- t.Fatalf("man.cachePut: %v", err)
- }
-
- // The expired cached cert should trigger a new cert issuance
- // and return without an error.
- hello := &tls.ClientHelloInfo{ServerName: "example.org"}
- testGetCertificate(t, man, "example.org", hello)
-}
-
-func TestGetCertificate_failedAttempt(t *testing.T) {
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusBadRequest)
- }))
- defer ts.Close()
-
- const example = "example.org"
- d := createCertRetryAfter
- f := testDidRemoveState
- defer func() {
- createCertRetryAfter = d
- testDidRemoveState = f
- }()
- createCertRetryAfter = 0
- done := make(chan struct{})
- testDidRemoveState = func(domain string) {
- if domain != example {
- t.Errorf("testDidRemoveState: domain = %q; want %q", domain, example)
- }
- close(done)
- }
-
- key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- t.Fatal(err)
- }
- man := &Manager{
- Prompt: AcceptTOS,
- Client: &acme.Client{
- Key: key,
- DirectoryURL: ts.URL,
- },
- }
- defer man.stopRenew()
- hello := &tls.ClientHelloInfo{ServerName: example}
- if _, err := man.GetCertificate(hello); err == nil {
- t.Error("GetCertificate: err is nil")
- }
- select {
- case <-time.After(5 * time.Second):
- t.Errorf("took too long to remove the %q state", example)
- case <-done:
- man.stateMu.Lock()
- defer man.stateMu.Unlock()
- if v, exist := man.state[example]; exist {
- t.Errorf("state exists for %q: %+v", example, v)
- }
- }
-}
-
-// startACMEServerStub runs an ACME server
-// The domain argument is the expected domain name of a certificate request.
-func startACMEServerStub(t *testing.T, man *Manager, domain string) (url string, finish func()) {
- // echo token-02 | shasum -a 256
- // then divide result in 2 parts separated by dot
- tokenCertName := "4e8eb87631187e9ff2153b56b13a4dec.13a35d002e485d60ff37354b32f665d9.token.acme.invalid"
- verifyTokenCert := func() {
- hello := &tls.ClientHelloInfo{ServerName: tokenCertName}
- _, err := man.GetCertificate(hello)
- if err != nil {
- t.Errorf("verifyTokenCert: GetCertificate(%q): %v", tokenCertName, err)
- return
- }
- }
-
- // ACME CA server stub
- var ca *httptest.Server
- ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Replay-Nonce", "nonce")
- if r.Method == "HEAD" {
- // a nonce request
- return
- }
-
- switch r.URL.Path {
- // discovery
- case "/":
- if err := discoTmpl.Execute(w, ca.URL); err != nil {
- t.Errorf("discoTmpl: %v", err)
- }
- // client key registration
- case "/new-reg":
- w.Write([]byte("{}"))
- // domain authorization
- case "/new-authz":
- w.Header().Set("Location", ca.URL+"/authz/1")
- w.WriteHeader(http.StatusCreated)
- if err := authzTmpl.Execute(w, ca.URL); err != nil {
- t.Errorf("authzTmpl: %v", err)
- }
- // accept tls-sni-02 challenge
- case "/challenge/2":
- verifyTokenCert()
- w.Write([]byte("{}"))
- // authorization status
- case "/authz/1":
- w.Write([]byte(`{"status": "valid"}`))
- // cert request
- case "/new-cert":
- var req struct {
- CSR string `json:"csr"`
- }
- decodePayload(&req, r.Body)
- b, _ := base64.RawURLEncoding.DecodeString(req.CSR)
- csr, err := x509.ParseCertificateRequest(b)
- if err != nil {
- t.Errorf("new-cert: CSR: %v", err)
- }
- if csr.Subject.CommonName != domain {
- t.Errorf("CommonName in CSR = %q; want %q", csr.Subject.CommonName, domain)
- }
- der, err := dummyCert(csr.PublicKey, domain)
- if err != nil {
- t.Errorf("new-cert: dummyCert: %v", err)
- }
- chainUp := fmt.Sprintf("<%s/ca-cert>; rel=up", ca.URL)
- w.Header().Set("Link", chainUp)
- w.WriteHeader(http.StatusCreated)
- w.Write(der)
- // CA chain cert
- case "/ca-cert":
- der, err := dummyCert(nil, "ca")
- if err != nil {
- t.Errorf("ca-cert: dummyCert: %v", err)
- }
- w.Write(der)
- default:
- t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
- }
- }))
- finish = func() {
- ca.Close()
-
- // make sure token cert was removed
- cancel := make(chan struct{})
- done := make(chan struct{})
- go func() {
- defer close(done)
- tick := time.NewTicker(100 * time.Millisecond)
- defer tick.Stop()
- for {
- hello := &tls.ClientHelloInfo{ServerName: tokenCertName}
- if _, err := man.GetCertificate(hello); err != nil {
- return
- }
- select {
- case <-tick.C:
- case <-cancel:
- return
- }
- }
- }()
- select {
- case <-done:
- case <-time.After(5 * time.Second):
- close(cancel)
- t.Error("token cert was not removed")
- <-done
- }
- }
- return ca.URL, finish
-}
-
-// tests man.GetCertificate flow using the provided hello argument.
-// The domain argument is the expected domain name of a certificate request.
-func testGetCertificate(t *testing.T, man *Manager, domain string, hello *tls.ClientHelloInfo) {
- url, finish := startACMEServerStub(t, man, domain)
- defer finish()
-
- // use EC key to run faster on 386
- key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- t.Fatal(err)
- }
- man.Client = &acme.Client{
- Key: key,
- DirectoryURL: url,
- }
-
- // simulate tls.Config.GetCertificate
- var tlscert *tls.Certificate
- done := make(chan struct{})
- go func() {
- tlscert, err = man.GetCertificate(hello)
- close(done)
- }()
- select {
- case <-time.After(time.Minute):
- t.Fatal("man.GetCertificate took too long to return")
- case <-done:
- }
- if err != nil {
- t.Fatalf("man.GetCertificate: %v", err)
- }
-
- // verify the tlscert is the same we responded with from the CA stub
- if len(tlscert.Certificate) == 0 {
- t.Fatal("len(tlscert.Certificate) is 0")
- }
- cert, err := x509.ParseCertificate(tlscert.Certificate[0])
- if err != nil {
- t.Fatalf("x509.ParseCertificate: %v", err)
- }
- if len(cert.DNSNames) == 0 || cert.DNSNames[0] != domain {
- t.Errorf("cert.DNSNames = %v; want %q", cert.DNSNames, domain)
- }
-
-}
-
-func TestVerifyHTTP01(t *testing.T) {
- var (
- http01 http.Handler
-
- authzCount int // num. of created authorizations
- didAcceptHTTP01 bool
- )
-
- verifyHTTPToken := func() {
- r := httptest.NewRequest("GET", "/.well-known/acme-challenge/token-http-01", nil)
- w := httptest.NewRecorder()
- http01.ServeHTTP(w, r)
- if w.Code != http.StatusOK {
- t.Errorf("http token: w.Code = %d; want %d", w.Code, http.StatusOK)
- }
- if v := string(w.Body.Bytes()); !strings.HasPrefix(v, "token-http-01.") {
- t.Errorf("http token value = %q; want 'token-http-01.' prefix", v)
- }
- }
-
- // ACME CA server stub, only the needed bits.
- // TODO: Merge this with startACMEServerStub, making it a configurable CA for testing.
- var ca *httptest.Server
- ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Replay-Nonce", "nonce")
- if r.Method == "HEAD" {
- // a nonce request
- return
- }
-
- switch r.URL.Path {
- // Discovery.
- case "/":
- if err := discoTmpl.Execute(w, ca.URL); err != nil {
- t.Errorf("discoTmpl: %v", err)
- }
- // Client key registration.
- case "/new-reg":
- w.Write([]byte("{}"))
- // New domain authorization.
- case "/new-authz":
- authzCount++
- w.Header().Set("Location", fmt.Sprintf("%s/authz/%d", ca.URL, authzCount))
- w.WriteHeader(http.StatusCreated)
- if err := authzTmpl.Execute(w, ca.URL); err != nil {
- t.Errorf("authzTmpl: %v", err)
- }
- // Accept tls-sni-02.
- case "/challenge/2":
- w.Write([]byte("{}"))
- // Reject tls-sni-01.
- case "/challenge/1":
- http.Error(w, "won't accept tls-sni-01", http.StatusBadRequest)
- // Should not accept dns-01.
- case "/challenge/dns-01":
- t.Errorf("dns-01 challenge was accepted")
- http.Error(w, "won't accept dns-01", http.StatusBadRequest)
- // Accept http-01.
- case "/challenge/http-01":
- didAcceptHTTP01 = true
- verifyHTTPToken()
- w.Write([]byte("{}"))
- // Authorization statuses.
- // Make tls-sni-xxx invalid.
- case "/authz/1", "/authz/2":
- w.Write([]byte(`{"status": "invalid"}`))
- case "/authz/3", "/authz/4":
- w.Write([]byte(`{"status": "valid"}`))
- default:
- http.NotFound(w, r)
- t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
- }
- }))
- defer ca.Close()
-
- key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- t.Fatal(err)
- }
- m := &Manager{
- Client: &acme.Client{
- Key: key,
- DirectoryURL: ca.URL,
- },
- }
- http01 = m.HTTPHandler(nil)
- if err := m.verify(context.Background(), m.Client, "example.org"); err != nil {
- t.Errorf("m.verify: %v", err)
- }
- // Only tls-sni-01, tls-sni-02 and http-01 must be accepted
- // The dns-01 challenge is unsupported.
- if authzCount != 3 {
- t.Errorf("authzCount = %d; want 3", authzCount)
- }
- if !didAcceptHTTP01 {
- t.Error("did not accept http-01 challenge")
- }
-}
-
-func TestHTTPHandlerDefaultFallback(t *testing.T) {
- tt := []struct {
- method, url string
- wantCode int
- wantLocation string
- }{
- {"GET", "http://example.org", 302, "https://example.org/"},
- {"GET", "http://example.org/foo", 302, "https://example.org/foo"},
- {"GET", "http://example.org/foo/bar/", 302, "https://example.org/foo/bar/"},
- {"GET", "http://example.org/?a=b", 302, "https://example.org/?a=b"},
- {"GET", "http://example.org/foo?a=b", 302, "https://example.org/foo?a=b"},
- {"GET", "http://example.org:80/foo?a=b", 302, "https://example.org:443/foo?a=b"},
- {"GET", "http://example.org:80/foo%20bar", 302, "https://example.org:443/foo%20bar"},
- {"GET", "http://[2602:d1:xxxx::c60a]:1234", 302, "https://[2602:d1:xxxx::c60a]:443/"},
- {"GET", "http://[2602:d1:xxxx::c60a]", 302, "https://[2602:d1:xxxx::c60a]/"},
- {"GET", "http://[2602:d1:xxxx::c60a]/foo?a=b", 302, "https://[2602:d1:xxxx::c60a]/foo?a=b"},
- {"HEAD", "http://example.org", 302, "https://example.org/"},
- {"HEAD", "http://example.org/foo", 302, "https://example.org/foo"},
- {"HEAD", "http://example.org/foo/bar/", 302, "https://example.org/foo/bar/"},
- {"HEAD", "http://example.org/?a=b", 302, "https://example.org/?a=b"},
- {"HEAD", "http://example.org/foo?a=b", 302, "https://example.org/foo?a=b"},
- {"POST", "http://example.org", 400, ""},
- {"PUT", "http://example.org", 400, ""},
- {"GET", "http://example.org/.well-known/acme-challenge/x", 404, ""},
- }
- var m Manager
- h := m.HTTPHandler(nil)
- for i, test := range tt {
- r := httptest.NewRequest(test.method, test.url, nil)
- w := httptest.NewRecorder()
- h.ServeHTTP(w, r)
- if w.Code != test.wantCode {
- t.Errorf("%d: w.Code = %d; want %d", i, w.Code, test.wantCode)
- t.Errorf("%d: body: %s", i, w.Body.Bytes())
- }
- if v := w.Header().Get("Location"); v != test.wantLocation {
- t.Errorf("%d: Location = %q; want %q", i, v, test.wantLocation)
- }
- }
-}
-
-func TestAccountKeyCache(t *testing.T) {
- m := Manager{Cache: newMemCache()}
- ctx := context.Background()
- k1, err := m.accountKey(ctx)
- if err != nil {
- t.Fatal(err)
- }
- k2, err := m.accountKey(ctx)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(k1, k2) {
- t.Errorf("account keys don't match: k1 = %#v; k2 = %#v", k1, k2)
- }
-}
-
-func TestCache(t *testing.T) {
- privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- t.Fatal(err)
- }
- tmpl := &x509.Certificate{
- SerialNumber: big.NewInt(1),
- Subject: pkix.Name{CommonName: "example.org"},
- NotAfter: time.Now().Add(time.Hour),
- }
- pub, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &privKey.PublicKey, privKey)
- if err != nil {
- t.Fatal(err)
- }
- tlscert := &tls.Certificate{
- Certificate: [][]byte{pub},
- PrivateKey: privKey,
- }
-
- man := &Manager{Cache: newMemCache()}
- defer man.stopRenew()
- ctx := context.Background()
- if err := man.cachePut(ctx, "example.org", tlscert); err != nil {
- t.Fatalf("man.cachePut: %v", err)
- }
- res, err := man.cacheGet(ctx, "example.org")
- if err != nil {
- t.Fatalf("man.cacheGet: %v", err)
- }
- if res == nil {
- t.Fatal("res is nil")
- }
-}
-
-func TestHostWhitelist(t *testing.T) {
- policy := HostWhitelist("example.com", "example.org", "*.example.net")
- tt := []struct {
- host string
- allow bool
- }{
- {"example.com", true},
- {"example.org", true},
- {"one.example.com", false},
- {"two.example.org", false},
- {"three.example.net", false},
- {"dummy", false},
- }
- for i, test := range tt {
- err := policy(nil, test.host)
- if err != nil && test.allow {
- t.Errorf("%d: policy(%q): %v; want nil", i, test.host, err)
- }
- if err == nil && !test.allow {
- t.Errorf("%d: policy(%q): nil; want an error", i, test.host)
- }
- }
-}
-
-func TestValidCert(t *testing.T) {
- key1, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- t.Fatal(err)
- }
- key2, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- t.Fatal(err)
- }
- key3, err := rsa.GenerateKey(rand.Reader, 512)
- if err != nil {
- t.Fatal(err)
- }
- cert1, err := dummyCert(key1.Public(), "example.org")
- if err != nil {
- t.Fatal(err)
- }
- cert2, err := dummyCert(key2.Public(), "example.org")
- if err != nil {
- t.Fatal(err)
- }
- cert3, err := dummyCert(key3.Public(), "example.org")
- if err != nil {
- t.Fatal(err)
- }
- now := time.Now()
- early, err := dateDummyCert(key1.Public(), now.Add(time.Hour), now.Add(2*time.Hour), "example.org")
- if err != nil {
- t.Fatal(err)
- }
- expired, err := dateDummyCert(key1.Public(), now.Add(-2*time.Hour), now.Add(-time.Hour), "example.org")
- if err != nil {
- t.Fatal(err)
- }
-
- tt := []struct {
- domain string
- key crypto.Signer
- cert [][]byte
- ok bool
- }{
- {"example.org", key1, [][]byte{cert1}, true},
- {"example.org", key3, [][]byte{cert3}, true},
- {"example.org", key1, [][]byte{cert1, cert2, cert3}, true},
- {"example.org", key1, [][]byte{cert1, {1}}, false},
- {"example.org", key1, [][]byte{{1}}, false},
- {"example.org", key1, [][]byte{cert2}, false},
- {"example.org", key2, [][]byte{cert1}, false},
- {"example.org", key1, [][]byte{cert3}, false},
- {"example.org", key3, [][]byte{cert1}, false},
- {"example.net", key1, [][]byte{cert1}, false},
- {"example.org", key1, [][]byte{early}, false},
- {"example.org", key1, [][]byte{expired}, false},
- }
- for i, test := range tt {
- leaf, err := validCert(test.domain, test.cert, test.key)
- if err != nil && test.ok {
- t.Errorf("%d: err = %v", i, err)
- }
- if err == nil && !test.ok {
- t.Errorf("%d: err is nil", i)
- }
- if err == nil && test.ok && leaf == nil {
- t.Errorf("%d: leaf is nil", i)
- }
- }
-}
-
-type cacheGetFunc func(ctx context.Context, key string) ([]byte, error)
-
-func (f cacheGetFunc) Get(ctx context.Context, key string) ([]byte, error) {
- return f(ctx, key)
-}
-
-func (f cacheGetFunc) Put(ctx context.Context, key string, data []byte) error {
- return fmt.Errorf("unsupported Put of %q = %q", key, data)
-}
-
-func (f cacheGetFunc) Delete(ctx context.Context, key string) error {
- return fmt.Errorf("unsupported Delete of %q", key)
-}
-
-func TestManagerGetCertificateBogusSNI(t *testing.T) {
- m := Manager{
- Prompt: AcceptTOS,
- Cache: cacheGetFunc(func(ctx context.Context, key string) ([]byte, error) {
- return nil, fmt.Errorf("cache.Get of %s", key)
- }),
- }
- tests := []struct {
- name string
- wantErr string
- }{
- {"foo.com", "cache.Get of foo.com"},
- {"foo.com.", "cache.Get of foo.com"},
- {`a\b.com`, "acme/autocert: server name contains invalid character"},
- {`a/b.com`, "acme/autocert: server name contains invalid character"},
- {"", "acme/autocert: missing server name"},
- {"foo", "acme/autocert: server name component count invalid"},
- {".foo", "acme/autocert: server name component count invalid"},
- {"foo.", "acme/autocert: server name component count invalid"},
- {"fo.o", "cache.Get of fo.o"},
- }
- for _, tt := range tests {
- _, err := m.GetCertificate(&tls.ClientHelloInfo{ServerName: tt.name})
- got := fmt.Sprint(err)
- if got != tt.wantErr {
- t.Errorf("GetCertificate(SNI = %q) = %q; want %q", tt.name, got, tt.wantErr)
- }
- }
-}
diff --git a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/cache.go b/cmd/ponzu/vendor/golang.org/x/crypto/autocert/cache.go
deleted file mode 100644
index 61a5fd2..0000000
--- a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/cache.go
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package autocert
-
-import (
- "context"
- "errors"
- "io/ioutil"
- "os"
- "path/filepath"
-)
-
-// ErrCacheMiss is returned when a certificate is not found in cache.
-var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss")
-
-// Cache is used by Manager to store and retrieve previously obtained certificates
-// as opaque data.
-//
-// The key argument of the methods refers to a domain name but need not be an FQDN.
-// Cache implementations should not rely on the key naming pattern.
-type Cache interface {
- // Get returns a certificate data for the specified key.
- // If there's no such key, Get returns ErrCacheMiss.
- Get(ctx context.Context, key string) ([]byte, error)
-
- // Put stores the data in the cache under the specified key.
- // Underlying implementations may use any data storage format,
- // as long as the reverse operation, Get, results in the original data.
- Put(ctx context.Context, key string, data []byte) error
-
- // Delete removes a certificate data from the cache under the specified key.
- // If there's no such key in the cache, Delete returns nil.
- Delete(ctx context.Context, key string) error
-}
-
-// DirCache implements Cache using a directory on the local filesystem.
-// If the directory does not exist, it will be created with 0700 permissions.
-type DirCache string
-
-// Get reads a certificate data from the specified file name.
-func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) {
- name = filepath.Join(string(d), name)
- var (
- data []byte
- err error
- done = make(chan struct{})
- )
- go func() {
- data, err = ioutil.ReadFile(name)
- close(done)
- }()
- select {
- case <-ctx.Done():
- return nil, ctx.Err()
- case <-done:
- }
- if os.IsNotExist(err) {
- return nil, ErrCacheMiss
- }
- return data, err
-}
-
-// Put writes the certificate data to the specified file name.
-// The file will be created with 0600 permissions.
-func (d DirCache) Put(ctx context.Context, name string, data []byte) error {
- if err := os.MkdirAll(string(d), 0700); err != nil {
- return err
- }
-
- done := make(chan struct{})
- var err error
- go func() {
- defer close(done)
- var tmp string
- if tmp, err = d.writeTempFile(name, data); err != nil {
- return
- }
- select {
- case <-ctx.Done():
- // Don't overwrite the file if the context was canceled.
- default:
- newName := filepath.Join(string(d), name)
- err = os.Rename(tmp, newName)
- }
- }()
- select {
- case <-ctx.Done():
- return ctx.Err()
- case <-done:
- }
- return err
-}
-
-// Delete removes the specified file name.
-func (d DirCache) Delete(ctx context.Context, name string) error {
- name = filepath.Join(string(d), name)
- var (
- err error
- done = make(chan struct{})
- )
- go func() {
- err = os.Remove(name)
- close(done)
- }()
- select {
- case <-ctx.Done():
- return ctx.Err()
- case <-done:
- }
- if err != nil && !os.IsNotExist(err) {
- return err
- }
- return nil
-}
-
-// writeTempFile writes b to a temporary file, closes the file and returns its path.
-func (d DirCache) writeTempFile(prefix string, b []byte) (string, error) {
- // TempFile uses 0600 permissions
- f, err := ioutil.TempFile(string(d), prefix)
- if err != nil {
- return "", err
- }
- if _, err := f.Write(b); err != nil {
- f.Close()
- return "", err
- }
- return f.Name(), f.Close()
-}
diff --git a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/cache_test.go b/cmd/ponzu/vendor/golang.org/x/crypto/autocert/cache_test.go
deleted file mode 100644
index 653b05b..0000000
--- a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/cache_test.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package autocert
-
-import (
- "context"
- "io/ioutil"
- "os"
- "path/filepath"
- "reflect"
- "testing"
-)
-
-// make sure DirCache satisfies Cache interface
-var _ Cache = DirCache("/")
-
-func TestDirCache(t *testing.T) {
- dir, err := ioutil.TempDir("", "autocert")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dir)
- dir = filepath.Join(dir, "certs") // a nonexistent dir
- cache := DirCache(dir)
- ctx := context.Background()
-
- // test cache miss
- if _, err := cache.Get(ctx, "nonexistent"); err != ErrCacheMiss {
- t.Errorf("get: %v; want ErrCacheMiss", err)
- }
-
- // test put/get
- b1 := []byte{1}
- if err := cache.Put(ctx, "dummy", b1); err != nil {
- t.Fatalf("put: %v", err)
- }
- b2, err := cache.Get(ctx, "dummy")
- if err != nil {
- t.Fatalf("get: %v", err)
- }
- if !reflect.DeepEqual(b1, b2) {
- t.Errorf("b1 = %v; want %v", b1, b2)
- }
- name := filepath.Join(dir, "dummy")
- if _, err := os.Stat(name); err != nil {
- t.Error(err)
- }
-
- // test delete
- if err := cache.Delete(ctx, "dummy"); err != nil {
- t.Fatalf("delete: %v", err)
- }
- if _, err := cache.Get(ctx, "dummy"); err != ErrCacheMiss {
- t.Errorf("get: %v; want ErrCacheMiss", err)
- }
-}
diff --git a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/example_test.go b/cmd/ponzu/vendor/golang.org/x/crypto/autocert/example_test.go
deleted file mode 100644
index 552a625..0000000
--- a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/example_test.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2017 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package autocert_test
-
-import (
- "crypto/tls"
- "fmt"
- "log"
- "net/http"
-
- "golang.org/x/crypto/acme/autocert"
-)
-
-func ExampleNewListener() {
- mux := http.NewServeMux()
- mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintf(w, "Hello, TLS user! Your config: %+v", r.TLS)
- })
- log.Fatal(http.Serve(autocert.NewListener("example.com"), mux))
-}
-
-func ExampleManager() {
- m := &autocert.Manager{
- Cache: autocert.DirCache("secret-dir"),
- Prompt: autocert.AcceptTOS,
- HostPolicy: autocert.HostWhitelist("example.org"),
- }
- go http.ListenAndServe(":http", m.HTTPHandler(nil))
- s := &http.Server{
- Addr: ":https",
- TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
- }
- s.ListenAndServeTLS("", "")
-}
diff --git a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/listener.go b/cmd/ponzu/vendor/golang.org/x/crypto/autocert/listener.go
deleted file mode 100644
index d744df0..0000000
--- a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/listener.go
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2017 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package autocert
-
-import (
- "crypto/tls"
- "log"
- "net"
- "os"
- "path/filepath"
- "runtime"
- "time"
-)
-
-// NewListener returns a net.Listener that listens on the standard TLS
-// port (443) on all interfaces and returns *tls.Conn connections with
-// LetsEncrypt certificates for the provided domain or domains.
-//
-// It enables one-line HTTPS servers:
-//
-// log.Fatal(http.Serve(autocert.NewListener("example.com"), handler))
-//
-// NewListener is a convenience function for a common configuration.
-// More complex or custom configurations can use the autocert.Manager
-// type instead.
-//
-// Use of this function implies acceptance of the LetsEncrypt Terms of
-// Service. If domains is not empty, the provided domains are passed
-// to HostWhitelist. If domains is empty, the listener will do
-// LetsEncrypt challenges for any requested domain, which is not
-// recommended.
-//
-// Certificates are cached in a "golang-autocert" directory under an
-// operating system-specific cache or temp directory. This may not
-// be suitable for servers spanning multiple machines.
-//
-// The returned listener uses a *tls.Config that enables HTTP/2, and
-// should only be used with servers that support HTTP/2.
-//
-// The returned Listener also enables TCP keep-alives on the accepted
-// connections. The returned *tls.Conn are returned before their TLS
-// handshake has completed.
-func NewListener(domains ...string) net.Listener {
- m := &Manager{
- Prompt: AcceptTOS,
- }
- if len(domains) > 0 {
- m.HostPolicy = HostWhitelist(domains...)
- }
- dir := cacheDir()
- if err := os.MkdirAll(dir, 0700); err != nil {
- log.Printf("warning: autocert.NewListener not using a cache: %v", err)
- } else {
- m.Cache = DirCache(dir)
- }
- return m.Listener()
-}
-
-// Listener listens on the standard TLS port (443) on all interfaces
-// and returns a net.Listener returning *tls.Conn connections.
-//
-// The returned listener uses a *tls.Config that enables HTTP/2, and
-// should only be used with servers that support HTTP/2.
-//
-// The returned Listener also enables TCP keep-alives on the accepted
-// connections. The returned *tls.Conn are returned before their TLS
-// handshake has completed.
-//
-// Unlike NewListener, it is the caller's responsibility to initialize
-// the Manager m's Prompt, Cache, HostPolicy, and other desired options.
-func (m *Manager) Listener() net.Listener {
- ln := &listener{
- m: m,
- conf: &tls.Config{
- GetCertificate: m.GetCertificate, // bonus: panic on nil m
- NextProtos: []string{"h2", "http/1.1"}, // Enable HTTP/2
- },
- }
- ln.tcpListener, ln.tcpListenErr = net.Listen("tcp", ":443")
- return ln
-}
-
-type listener struct {
- m *Manager
- conf *tls.Config
-
- tcpListener net.Listener
- tcpListenErr error
-}
-
-func (ln *listener) Accept() (net.Conn, error) {
- if ln.tcpListenErr != nil {
- return nil, ln.tcpListenErr
- }
- conn, err := ln.tcpListener.Accept()
- if err != nil {
- return nil, err
- }
- tcpConn := conn.(*net.TCPConn)
-
- // Because Listener is a convenience function, help out with
- // this too. This is not possible for the caller to set once
- // we return a *tcp.Conn wrapping an inaccessible net.Conn.
- // If callers don't want this, they can do things the manual
- // way and tweak as needed. But this is what net/http does
- // itself, so copy that. If net/http changes, we can change
- // here too.
- tcpConn.SetKeepAlive(true)
- tcpConn.SetKeepAlivePeriod(3 * time.Minute)
-
- return tls.Server(tcpConn, ln.conf), nil
-}
-
-func (ln *listener) Addr() net.Addr {
- if ln.tcpListener != nil {
- return ln.tcpListener.Addr()
- }
- // net.Listen failed. Return something non-nil in case callers
- // call Addr before Accept:
- return &net.TCPAddr{IP: net.IP{0, 0, 0, 0}, Port: 443}
-}
-
-func (ln *listener) Close() error {
- if ln.tcpListenErr != nil {
- return ln.tcpListenErr
- }
- return ln.tcpListener.Close()
-}
-
-func homeDir() string {
- if runtime.GOOS == "windows" {
- return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
- }
- if h := os.Getenv("HOME"); h != "" {
- return h
- }
- return "/"
-}
-
-func cacheDir() string {
- const base = "golang-autocert"
- switch runtime.GOOS {
- case "darwin":
- return filepath.Join(homeDir(), "Library", "Caches", base)
- case "windows":
- for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} {
- if v := os.Getenv(ev); v != "" {
- return filepath.Join(v, base)
- }
- }
- // Worst case:
- return filepath.Join(homeDir(), base)
- }
- if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" {
- return filepath.Join(xdg, base)
- }
- return filepath.Join(homeDir(), ".cache", base)
-}
diff --git a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/renewal.go b/cmd/ponzu/vendor/golang.org/x/crypto/autocert/renewal.go
deleted file mode 100644
index 6c5da2b..0000000
--- a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/renewal.go
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package autocert
-
-import (
- "context"
- "crypto"
- "sync"
- "time"
-)
-
-// renewJitter is the maximum deviation from Manager.RenewBefore.
-const renewJitter = time.Hour
-
-// domainRenewal tracks the state used by the periodic timers
-// renewing a single domain's cert.
-type domainRenewal struct {
- m *Manager
- domain string
- key crypto.Signer
-
- timerMu sync.Mutex
- timer *time.Timer
-}
-
-// start starts a cert renewal timer at the time
-// defined by the certificate expiration time exp.
-//
-// If the timer is already started, calling start is a noop.
-func (dr *domainRenewal) start(exp time.Time) {
- dr.timerMu.Lock()
- defer dr.timerMu.Unlock()
- if dr.timer != nil {
- return
- }
- dr.timer = time.AfterFunc(dr.next(exp), dr.renew)
-}
-
-// stop stops the cert renewal timer.
-// If the timer is already stopped, calling stop is a noop.
-func (dr *domainRenewal) stop() {
- dr.timerMu.Lock()
- defer dr.timerMu.Unlock()
- if dr.timer == nil {
- return
- }
- dr.timer.Stop()
- dr.timer = nil
-}
-
-// renew is called periodically by a timer.
-// The first renew call is kicked off by dr.start.
-func (dr *domainRenewal) renew() {
- dr.timerMu.Lock()
- defer dr.timerMu.Unlock()
- if dr.timer == nil {
- return
- }
-
- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
- defer cancel()
- // TODO: rotate dr.key at some point?
- next, err := dr.do(ctx)
- if err != nil {
- next = renewJitter / 2
- next += time.Duration(pseudoRand.int63n(int64(next)))
- }
- dr.timer = time.AfterFunc(next, dr.renew)
- testDidRenewLoop(next, err)
-}
-
-// do is similar to Manager.createCert but it doesn't lock a Manager.state item.
-// Instead, it requests a new certificate independently and, upon success,
-// replaces dr.m.state item with a new one and updates cache for the given domain.
-//
-// It may return immediately if the expiration date of the currently cached cert
-// is far enough in the future.
-//
-// The returned value is a time interval after which the renewal should occur again.
-func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) {
- // a race is likely unavoidable in a distributed environment
- // but we try nonetheless
- if tlscert, err := dr.m.cacheGet(ctx, dr.domain); err == nil {
- next := dr.next(tlscert.Leaf.NotAfter)
- if next > dr.m.renewBefore()+renewJitter {
- return next, nil
- }
- }
-
- der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.domain)
- if err != nil {
- return 0, err
- }
- state := &certState{
- key: dr.key,
- cert: der,
- leaf: leaf,
- }
- tlscert, err := state.tlscert()
- if err != nil {
- return 0, err
- }
- dr.m.cachePut(ctx, dr.domain, tlscert)
- dr.m.stateMu.Lock()
- defer dr.m.stateMu.Unlock()
- // m.state is guaranteed to be non-nil at this point
- dr.m.state[dr.domain] = state
- return dr.next(leaf.NotAfter), nil
-}
-
-func (dr *domainRenewal) next(expiry time.Time) time.Duration {
- d := expiry.Sub(timeNow()) - dr.m.renewBefore()
- // add a bit of randomness to renew deadline
- n := pseudoRand.int63n(int64(renewJitter))
- d -= time.Duration(n)
- if d < 0 {
- return 0
- }
- return d
-}
-
-var testDidRenewLoop = func(next time.Duration, err error) {}
diff --git a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/renewal_test.go b/cmd/ponzu/vendor/golang.org/x/crypto/autocert/renewal_test.go
deleted file mode 100644
index 11d40ff..0000000
--- a/cmd/ponzu/vendor/golang.org/x/crypto/autocert/renewal_test.go
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package autocert
-
-import (
- "context"
- "crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rand"
- "crypto/tls"
- "crypto/x509"
- "encoding/base64"
- "fmt"
- "net/http"
- "net/http/httptest"
- "testing"
- "time"
-
- "golang.org/x/crypto/acme"
-)
-
-func TestRenewalNext(t *testing.T) {
- now := time.Now()
- timeNow = func() time.Time { return now }
- defer func() { timeNow = time.Now }()
-
- man := &Manager{RenewBefore: 7 * 24 * time.Hour}
- defer man.stopRenew()
- tt := []struct {
- expiry time.Time
- min, max time.Duration
- }{
- {now.Add(90 * 24 * time.Hour), 83*24*time.Hour - renewJitter, 83 * 24 * time.Hour},
- {now.Add(time.Hour), 0, 1},
- {now, 0, 1},
- {now.Add(-time.Hour), 0, 1},
- }
-
- dr := &domainRenewal{m: man}
- for i, test := range tt {
- next := dr.next(test.expiry)
- if next < test.min || test.max < next {
- t.Errorf("%d: next = %v; want between %v and %v", i, next, test.min, test.max)
- }
- }
-}
-
-func TestRenewFromCache(t *testing.T) {
- const domain = "example.org"
-
- // ACME CA server stub
- var ca *httptest.Server
- ca = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Replay-Nonce", "nonce")
- if r.Method == "HEAD" {
- // a nonce request
- return
- }
-
- switch r.URL.Path {
- // discovery
- case "/":
- if err := discoTmpl.Execute(w, ca.URL); err != nil {
- t.Fatalf("discoTmpl: %v", err)
- }
- // client key registration
- case "/new-reg":
- w.Write([]byte("{}"))
- // domain authorization
- case "/new-authz":
- w.Header().Set("Location", ca.URL+"/authz/1")
- w.WriteHeader(http.StatusCreated)
- w.Write([]byte(`{"status": "valid"}`))
- // cert request
- case "/new-cert":
- var req struct {
- CSR string `json:"csr"`
- }
- decodePayload(&req, r.Body)
- b, _ := base64.RawURLEncoding.DecodeString(req.CSR)
- csr, err := x509.ParseCertificateRequest(b)
- if err != nil {
- t.Fatalf("new-cert: CSR: %v", err)
- }
- der, err := dummyCert(csr.PublicKey, domain)
- if err != nil {
- t.Fatalf("new-cert: dummyCert: %v", err)
- }
- chainUp := fmt.Sprintf("<%s/ca-cert>; rel=up", ca.URL)
- w.Header().Set("Link", chainUp)
- w.WriteHeader(http.StatusCreated)
- w.Write(der)
- // CA chain cert
- case "/ca-cert":
- der, err := dummyCert(nil, "ca")
- if err != nil {
- t.Fatalf("ca-cert: dummyCert: %v", err)
- }
- w.Write(der)
- default:
- t.Errorf("unrecognized r.URL.Path: %s", r.URL.Path)
- }
- }))
- defer ca.Close()
-
- // use EC key to run faster on 386
- key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- t.Fatal(err)
- }
- man := &Manager{
- Prompt: AcceptTOS,
- Cache: newMemCache(),
- RenewBefore: 24 * time.Hour,
- Client: &acme.Client{
- Key: key,
- DirectoryURL: ca.URL,
- },
- }
- defer man.stopRenew()
-
- // cache an almost expired cert
- now := time.Now()
- cert, err := dateDummyCert(key.Public(), now.Add(-2*time.Hour), now.Add(time.Minute), domain)
- if err != nil {
- t.Fatal(err)
- }
- tlscert := &tls.Certificate{PrivateKey: key, Certificate: [][]byte{cert}}
- if err := man.cachePut(context.Background(), domain, tlscert); err != nil {
- t.Fatal(err)
- }
-
- // veriy the renewal happened
- defer func() {
- testDidRenewLoop = func(next time.Duration, err error) {}
- }()
- done := make(chan struct{})
- testDidRenewLoop = func(next time.Duration, err error) {
- defer close(done)
- if err != nil {
- t.Errorf("testDidRenewLoop: %v", err)
- }
- // Next should be about 90 days:
- // dummyCert creates 90days expiry + account for man.RenewBefore.
- // Previous expiration was within 1 min.
- future := 88 * 24 * time.Hour
- if next < future {
- t.Errorf("testDidRenewLoop: next = %v; want >= %v", next, future)
- }
-
- // ensure the new cert is cached
- after := time.Now().Add(future)
- tlscert, err := man.cacheGet(context.Background(), domain)
- if err != nil {
- t.Fatalf("man.cacheGet: %v", err)
- }
- if !tlscert.Leaf.NotAfter.After(after) {
- t.Errorf("cache leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after)
- }
-
- // verify the old cert is also replaced in memory
- man.stateMu.Lock()
- defer man.stateMu.Unlock()
- s := man.state[domain]
- if s == nil {
- t.Fatalf("m.state[%q] is nil", domain)
- }
- tlscert, err = s.tlscert()
- if err != nil {
- t.Fatalf("s.tlscert: %v", err)
- }
- if !tlscert.Leaf.NotAfter.After(after) {
- t.Errorf("state leaf.NotAfter = %v; want > %v", tlscert.Leaf.NotAfter, after)
- }
- }
-
- // trigger renew
- hello := &tls.ClientHelloInfo{ServerName: domain}
- if _, err := man.GetCertificate(hello); err != nil {
- t.Fatal(err)
- }
-
- // wait for renew loop
- select {
- case <-time.After(10 * time.Second):
- t.Fatal("renew took too long to occur")
- case <-done:
- }
-}
diff --git a/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/base64.go b/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/base64.go
deleted file mode 100644
index fc31160..0000000
--- a/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/base64.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package bcrypt
-
-import "encoding/base64"
-
-const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-
-var bcEncoding = base64.NewEncoding(alphabet)
-
-func base64Encode(src []byte) []byte {
- n := bcEncoding.EncodedLen(len(src))
- dst := make([]byte, n)
- bcEncoding.Encode(dst, src)
- for dst[n-1] == '=' {
- n--
- }
- return dst[:n]
-}
-
-func base64Decode(src []byte) ([]byte, error) {
- numOfEquals := 4 - (len(src) % 4)
- for i := 0; i < numOfEquals; i++ {
- src = append(src, '=')
- }
-
- dst := make([]byte, bcEncoding.DecodedLen(len(src)))
- n, err := bcEncoding.Decode(dst, src)
- if err != nil {
- return nil, err
- }
- return dst[:n], nil
-}
diff --git a/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt.go b/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt.go
deleted file mode 100644
index f8b807f..0000000
--- a/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt.go
+++ /dev/null
@@ -1,294 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing
-// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
-package bcrypt // import "golang.org/x/crypto/bcrypt"
-
-// The code is a port of Provos and Mazières's C implementation.
-import (
- "crypto/rand"
- "crypto/subtle"
- "errors"
- "fmt"
- "golang.org/x/crypto/blowfish"
- "io"
- "strconv"
-)
-
-const (
- MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword
- MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword
- DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword
-)
-
-// The error returned from CompareHashAndPassword when a password and hash do
-// not match.
-var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password")
-
-// The error returned from CompareHashAndPassword when a hash is too short to
-// be a bcrypt hash.
-var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password")
-
-// The error returned from CompareHashAndPassword when a hash was created with
-// a bcrypt algorithm newer than this implementation.
-type HashVersionTooNewError byte
-
-func (hv HashVersionTooNewError) Error() string {
- return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion)
-}
-
-// The error returned from CompareHashAndPassword when a hash starts with something other than '$'
-type InvalidHashPrefixError byte
-
-func (ih InvalidHashPrefixError) Error() string {
- return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih))
-}
-
-type InvalidCostError int
-
-func (ic InvalidCostError) Error() string {
- return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost))
-}
-
-const (
- majorVersion = '2'
- minorVersion = 'a'
- maxSaltSize = 16
- maxCryptedHashSize = 23
- encodedSaltSize = 22
- encodedHashSize = 31
- minHashSize = 59
-)
-
-// magicCipherData is an IV for the 64 Blowfish encryption calls in
-// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes.
-var magicCipherData = []byte{
- 0x4f, 0x72, 0x70, 0x68,
- 0x65, 0x61, 0x6e, 0x42,
- 0x65, 0x68, 0x6f, 0x6c,
- 0x64, 0x65, 0x72, 0x53,
- 0x63, 0x72, 0x79, 0x44,
- 0x6f, 0x75, 0x62, 0x74,
-}
-
-type hashed struct {
- hash []byte
- salt []byte
- cost int // allowed range is MinCost to MaxCost
- major byte
- minor byte
-}
-
-// GenerateFromPassword returns the bcrypt hash of the password at the given
-// cost. If the cost given is less than MinCost, the cost will be set to
-// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
-// to compare the returned hashed password with its cleartext version.
-func GenerateFromPassword(password []byte, cost int) ([]byte, error) {
- p, err := newFromPassword(password, cost)
- if err != nil {
- return nil, err
- }
- return p.Hash(), nil
-}
-
-// CompareHashAndPassword compares a bcrypt hashed password with its possible
-// plaintext equivalent. Returns nil on success, or an error on failure.
-func CompareHashAndPassword(hashedPassword, password []byte) error {
- p, err := newFromHash(hashedPassword)
- if err != nil {
- return err
- }
-
- otherHash, err := bcrypt(password, p.cost, p.salt)
- if err != nil {
- return err
- }
-
- otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
- if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
- return nil
- }
-
- return ErrMismatchedHashAndPassword
-}
-
-// Cost returns the hashing cost used to create the given hashed
-// password. When, in the future, the hashing cost of a password system needs
-// to be increased in order to adjust for greater computational power, this
-// function allows one to establish which passwords need to be updated.
-func Cost(hashedPassword []byte) (int, error) {
- p, err := newFromHash(hashedPassword)
- if err != nil {
- return 0, err
- }
- return p.cost, nil
-}
-
-func newFromPassword(password []byte, cost int) (*hashed, error) {
- if cost < MinCost {
- cost = DefaultCost
- }
- p := new(hashed)
- p.major = majorVersion
- p.minor = minorVersion
-
- err := checkCost(cost)
- if err != nil {
- return nil, err
- }
- p.cost = cost
-
- unencodedSalt := make([]byte, maxSaltSize)
- _, err = io.ReadFull(rand.Reader, unencodedSalt)
- if err != nil {
- return nil, err
- }
-
- p.salt = base64Encode(unencodedSalt)
- hash, err := bcrypt(password, p.cost, p.salt)
- if err != nil {
- return nil, err
- }
- p.hash = hash
- return p, err
-}
-
-func newFromHash(hashedSecret []byte) (*hashed, error) {
- if len(hashedSecret) < minHashSize {
- return nil, ErrHashTooShort
- }
- p := new(hashed)
- n, err := p.decodeVersion(hashedSecret)
- if err != nil {
- return nil, err
- }
- hashedSecret = hashedSecret[n:]
- n, err = p.decodeCost(hashedSecret)
- if err != nil {
- return nil, err
- }
- hashedSecret = hashedSecret[n:]
-
- // The "+2" is here because we'll have to append at most 2 '=' to the salt
- // when base64 decoding it in expensiveBlowfishSetup().
- p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2)
- copy(p.salt, hashedSecret[:encodedSaltSize])
-
- hashedSecret = hashedSecret[encodedSaltSize:]
- p.hash = make([]byte, len(hashedSecret))
- copy(p.hash, hashedSecret)
-
- return p, nil
-}
-
-func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) {
- cipherData := make([]byte, len(magicCipherData))
- copy(cipherData, magicCipherData)
-
- c, err := expensiveBlowfishSetup(password, uint32(cost), salt)
- if err != nil {
- return nil, err
- }
-
- for i := 0; i < 24; i += 8 {
- for j := 0; j < 64; j++ {
- c.Encrypt(cipherData[i:i+8], cipherData[i:i+8])
- }
- }
-
- // Bug compatibility with C bcrypt implementations. We only encode 23 of
- // the 24 bytes encrypted.
- hsh := base64Encode(cipherData[:maxCryptedHashSize])
- return hsh, nil
-}
-
-func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) {
-
- csalt, err := base64Decode(salt)
- if err != nil {
- return nil, err
- }
-
- // Bug compatibility with C bcrypt implementations. They use the trailing
- // NULL in the key string during expansion.
- ckey := append(key, 0)
-
- c, err := blowfish.NewSaltedCipher(ckey, csalt)
- if err != nil {
- return nil, err
- }
-
- var i, rounds uint64
- rounds = 1 << cost
- for i = 0; i < rounds; i++ {
- blowfish.ExpandKey(ckey, c)
- blowfish.ExpandKey(csalt, c)
- }
-
- return c, nil
-}
-
-func (p *hashed) Hash() []byte {
- arr := make([]byte, 60)
- arr[0] = '$'
- arr[1] = p.major
- n := 2
- if p.minor != 0 {
- arr[2] = p.minor
- n = 3
- }
- arr[n] = '$'
- n += 1
- copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost)))
- n += 2
- arr[n] = '$'
- n += 1
- copy(arr[n:], p.salt)
- n += encodedSaltSize
- copy(arr[n:], p.hash)
- n += encodedHashSize
- return arr[:n]
-}
-
-func (p *hashed) decodeVersion(sbytes []byte) (int, error) {
- if sbytes[0] != '$' {
- return -1, InvalidHashPrefixError(sbytes[0])
- }
- if sbytes[1] > majorVersion {
- return -1, HashVersionTooNewError(sbytes[1])
- }
- p.major = sbytes[1]
- n := 3
- if sbytes[2] != '$' {
- p.minor = sbytes[2]
- n++
- }
- return n, nil
-}
-
-// sbytes should begin where decodeVersion left off.
-func (p *hashed) decodeCost(sbytes []byte) (int, error) {
- cost, err := strconv.Atoi(string(sbytes[0:2]))
- if err != nil {
- return -1, err
- }
- err = checkCost(cost)
- if err != nil {
- return -1, err
- }
- p.cost = cost
- return 3, nil
-}
-
-func (p *hashed) String() string {
- return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor)
-}
-
-func checkCost(cost int) error {
- if cost < MinCost || cost > MaxCost {
- return InvalidCostError(cost)
- }
- return nil
-}
diff --git a/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go b/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
deleted file mode 100644
index f08a6f5..0000000
--- a/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package bcrypt
-
-import (
- "bytes"
- "fmt"
- "testing"
-)
-
-func TestBcryptingIsEasy(t *testing.T) {
- pass := []byte("mypassword")
- hp, err := GenerateFromPassword(pass, 0)
- if err != nil {
- t.Fatalf("GenerateFromPassword error: %s", err)
- }
-
- if CompareHashAndPassword(hp, pass) != nil {
- t.Errorf("%v should hash %s correctly", hp, pass)
- }
-
- notPass := "notthepass"
- err = CompareHashAndPassword(hp, []byte(notPass))
- if err != ErrMismatchedHashAndPassword {
- t.Errorf("%v and %s should be mismatched", hp, notPass)
- }
-}
-
-func TestBcryptingIsCorrect(t *testing.T) {
- pass := []byte("allmine")
- salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
- expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
-
- hash, err := bcrypt(pass, 10, salt)
- if err != nil {
- t.Fatalf("bcrypt blew up: %v", err)
- }
- if !bytes.HasSuffix(expectedHash, hash) {
- t.Errorf("%v should be the suffix of %v", hash, expectedHash)
- }
-
- h, err := newFromHash(expectedHash)
- if err != nil {
- t.Errorf("Unable to parse %s: %v", string(expectedHash), err)
- }
-
- // This is not the safe way to compare these hashes. We do this only for
- // testing clarity. Use bcrypt.CompareHashAndPassword()
- if err == nil && !bytes.Equal(expectedHash, h.Hash()) {
- t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash)
- }
-}
-
-func TestVeryShortPasswords(t *testing.T) {
- key := []byte("k")
- salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
- _, err := bcrypt(key, 10, salt)
- if err != nil {
- t.Errorf("One byte key resulted in error: %s", err)
- }
-}
-
-func TestTooLongPasswordsWork(t *testing.T) {
- salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
- // One byte over the usual 56 byte limit that blowfish has
- tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456")
- tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C")
- hash, err := bcrypt(tooLongPass, 10, salt)
- if err != nil {
- t.Fatalf("bcrypt blew up on long password: %v", err)
- }
- if !bytes.HasSuffix(tooLongExpected, hash) {
- t.Errorf("%v should be the suffix of %v", hash, tooLongExpected)
- }
-}
-
-type InvalidHashTest struct {
- err error
- hash []byte
-}
-
-var invalidTests = []InvalidHashTest{
- {ErrHashTooShort, []byte("$2a$10$fooo")},
- {ErrHashTooShort, []byte("$2a")},
- {HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
- {InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
- {InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
-}
-
-func TestInvalidHashErrors(t *testing.T) {
- check := func(name string, expected, err error) {
- if err == nil {
- t.Errorf("%s: Should have returned an error", name)
- }
- if err != nil && err != expected {
- t.Errorf("%s gave err %v but should have given %v", name, err, expected)
- }
- }
- for _, iht := range invalidTests {
- _, err := newFromHash(iht.hash)
- check("newFromHash", iht.err, err)
- err = CompareHashAndPassword(iht.hash, []byte("anything"))
- check("CompareHashAndPassword", iht.err, err)
- }
-}
-
-func TestUnpaddedBase64Encoding(t *testing.T) {
- original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30}
- encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe")
-
- encoded := base64Encode(original)
-
- if !bytes.Equal(encodedOriginal, encoded) {
- t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal)
- }
-
- decoded, err := base64Decode(encodedOriginal)
- if err != nil {
- t.Fatalf("base64Decode blew up: %s", err)
- }
-
- if !bytes.Equal(decoded, original) {
- t.Errorf("Decoded %v should have equaled %v", decoded, original)
- }
-}
-
-func TestCost(t *testing.T) {
- suffix := "XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C"
- for _, vers := range []string{"2a", "2"} {
- for _, cost := range []int{4, 10} {
- s := fmt.Sprintf("$%s$%02d$%s", vers, cost, suffix)
- h := []byte(s)
- actual, err := Cost(h)
- if err != nil {
- t.Errorf("Cost, error: %s", err)
- continue
- }
- if actual != cost {
- t.Errorf("Cost, expected: %d, actual: %d", cost, actual)
- }
- }
- }
- _, err := Cost([]byte("$a$a$" + suffix))
- if err == nil {
- t.Errorf("Cost, malformed but no error returned")
- }
-}
-
-func TestCostValidationInHash(t *testing.T) {
- if testing.Short() {
- return
- }
-
- pass := []byte("mypassword")
-
- for c := 0; c < MinCost; c++ {
- p, _ := newFromPassword(pass, c)
- if p.cost != DefaultCost {
- t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost)
- }
- }
-
- p, _ := newFromPassword(pass, 14)
- if p.cost != 14 {
- t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost)
- }
-
- hp, _ := newFromHash(p.Hash())
- if p.cost != hp.cost {
- t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost)
- }
-
- _, err := newFromPassword(pass, 32)
- if err == nil {
- t.Fatalf("newFromPassword: should return a cost error")
- }
- if err != InvalidCostError(32) {
- t.Errorf("newFromPassword: should return cost error, got %#v", err)
- }
-}
-
-func TestCostReturnsWithLeadingZeroes(t *testing.T) {
- hp, _ := newFromPassword([]byte("abcdefgh"), 7)
- cost := hp.Hash()[4:7]
- expected := []byte("07$")
-
- if !bytes.Equal(expected, cost) {
- t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected)
- }
-}
-
-func TestMinorNotRequired(t *testing.T) {
- noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
- h, err := newFromHash(noMinorHash)
- if err != nil {
- t.Fatalf("No minor hash blew up: %s", err)
- }
- if h.minor != 0 {
- t.Errorf("Should leave minor version at 0, but was %d", h.minor)
- }
-
- if !bytes.Equal(noMinorHash, h.Hash()) {
- t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash())
- }
-}
-
-func BenchmarkEqual(b *testing.B) {
- b.StopTimer()
- passwd := []byte("somepasswordyoulike")
- hash, _ := GenerateFromPassword(passwd, 10)
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- CompareHashAndPassword(hash, passwd)
- }
-}
-
-func BenchmarkGeneration(b *testing.B) {
- b.StopTimer()
- passwd := []byte("mylongpassword1234")
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- GenerateFromPassword(passwd, 10)
- }
-}