diff options
author | Christopher Speller <crspeller@gmail.com> | 2017-03-13 12:54:22 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-13 12:54:22 -0400 |
commit | c281ee3b61e8ab53ff118866d72618ae8cce582b (patch) | |
tree | 776e7bdf6c8bfbb9a1dee5976496ab065959991f /vendor/github.com/xenolf/lego | |
parent | 3ada7a41a7fb13abef19dd63dc56b720900dbaa9 (diff) | |
download | chat-c281ee3b61e8ab53ff118866d72618ae8cce582b.tar.gz chat-c281ee3b61e8ab53ff118866d72618ae8cce582b.tar.bz2 chat-c281ee3b61e8ab53ff118866d72618ae8cce582b.zip |
Updating server dependancies. Also adding github.com/jaytaylor/html2text and gopkg.in/gomail.v2 (#5748)
Diffstat (limited to 'vendor/github.com/xenolf/lego')
-rw-r--r-- | vendor/github.com/xenolf/lego/README.md | 6 | ||||
-rw-r--r-- | vendor/github.com/xenolf/lego/acme/client.go | 9 | ||||
-rw-r--r-- | vendor/github.com/xenolf/lego/acme/client_test.go | 71 | ||||
-rw-r--r-- | vendor/github.com/xenolf/lego/acme/error.go | 15 | ||||
-rw-r--r-- | vendor/github.com/xenolf/lego/acme/http.go | 10 | ||||
-rw-r--r-- | vendor/github.com/xenolf/lego/acme/jws.go | 93 | ||||
-rw-r--r-- | vendor/github.com/xenolf/lego/providers/http/memcached/memcached.go | 3 |
7 files changed, 165 insertions, 42 deletions
diff --git a/vendor/github.com/xenolf/lego/README.md b/vendor/github.com/xenolf/lego/README.md index 9be562944..852f0a833 100644 --- a/vendor/github.com/xenolf/lego/README.md +++ b/vendor/github.com/xenolf/lego/README.md @@ -23,7 +23,11 @@ To build lego inside a Docker container, just run ``` docker build -t lego . ``` - +##### From the package manager +- [ArchLinux (AUR)](https://aur.archlinux.org/packages/lego-git): +``` +yaourt -S lego-git +``` #### Features - Register with CA diff --git a/vendor/github.com/xenolf/lego/acme/client.go b/vendor/github.com/xenolf/lego/acme/client.go index e824f5080..ba56e796c 100644 --- a/vendor/github.com/xenolf/lego/acme/client.go +++ b/vendor/github.com/xenolf/lego/acme/client.go @@ -535,6 +535,7 @@ func (c *Client) getChallenges(domains []string) ([]authorizationResource, map[s links := parseLinks(hdr["Link"]) if links["next"] == "" { logf("[ERROR][%s] acme: Server did not provide next link to proceed", domain) + errc <- domainError{Domain: domain, Error: errors.New("Server did not provide next link to proceed")} return } @@ -560,12 +561,20 @@ func (c *Client) getChallenges(domains []string) ([]authorizationResource, map[s } } + logAuthz(challenges) + close(resc) close(errc) return challenges, failures } +func logAuthz(authz []authorizationResource) { + for _, auth := range authz { + logf("[INFO][%s] AuthURL: %s", auth.Domain, auth.AuthURL) + } +} + 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!") diff --git a/vendor/github.com/xenolf/lego/acme/client_test.go b/vendor/github.com/xenolf/lego/acme/client_test.go index e309554f3..b18334c8a 100644 --- a/vendor/github.com/xenolf/lego/acme/client_test.go +++ b/vendor/github.com/xenolf/lego/acme/client_test.go @@ -10,6 +10,7 @@ import ( "net/http/httptest" "strings" "testing" + "time" ) func TestNewClient(t *testing.T) { @@ -118,6 +119,39 @@ func TestClientOptPort(t *testing.T) { } } +func TestNotHoldingLockWhileMakingHTTPRequests(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + time.Sleep(250 * time.Millisecond) + w.Header().Add("Replay-Nonce", "12345") + w.Header().Add("Retry-After", "0") + writeJSONResponse(w, &challenge{Type: "http-01", Status: "Valid", URI: "http://example.com/", Token: "token"}) + })) + defer ts.Close() + + privKey, _ := rsa.GenerateKey(rand.Reader, 512) + j := &jws{privKey: privKey, directoryURL: ts.URL} + ch := make(chan bool) + resultCh := make(chan bool) + go func() { + j.Nonce() + ch <- true + }() + go func() { + j.Nonce() + ch <- true + }() + go func() { + <-ch + <-ch + resultCh <- true + }() + select { + case <-resultCh: + case <-time.After(400 * time.Millisecond): + t.Fatal("JWS is probably holding a lock while making HTTP request") + } +} + func TestValidate(t *testing.T) { var statuses []string ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -168,6 +202,43 @@ func TestValidate(t *testing.T) { } } +func TestGetChallenges(t *testing.T) { + var ts *httptest.Server + ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case "GET", "HEAD": + w.Header().Add("Replay-Nonce", "12345") + w.Header().Add("Retry-After", "0") + writeJSONResponse(w, directory{NewAuthzURL: ts.URL, NewCertURL: ts.URL, NewRegURL: ts.URL, RevokeCertURL: ts.URL}) + case "POST": + writeJSONResponse(w, authorization{}) + } + })) + defer ts.Close() + + keyBits := 512 // small value keeps test fast + keyType := RSA2048 + key, err := rsa.GenerateKey(rand.Reader, keyBits) + if err != nil { + t.Fatal("Could not generate test key:", err) + } + user := mockUser{ + email: "test@test.com", + regres: &RegistrationResource{NewAuthzURL: ts.URL}, + privatekey: key, + } + + client, err := NewClient(ts.URL, user, keyType) + if err != nil { + t.Fatalf("Could not create client: %v", err) + } + + _, failures := client.getChallenges([]string{"example.com"}) + if failures["example.com"] == nil { + t.Fatal("Expecting \"Server did not provide next link to proceed\" error, got nil") + } +} + // writeJSONResponse marshals the body as JSON and writes it to the response. func writeJSONResponse(w http.ResponseWriter, body interface{}) { bs, err := json.Marshal(body) diff --git a/vendor/github.com/xenolf/lego/acme/error.go b/vendor/github.com/xenolf/lego/acme/error.go index 6d7013cf1..e4bc934c2 100644 --- a/vendor/github.com/xenolf/lego/acme/error.go +++ b/vendor/github.com/xenolf/lego/acme/error.go @@ -8,7 +8,10 @@ import ( "strings" ) -const tosAgreementError = "Must agree to subscriber agreement before any further actions" +const ( + tosAgreementError = "Must agree to subscriber agreement before any further actions" + invalidNonceError = "JWS has invalid anti-replay nonce" +) // RemoteError is the base type for all errors specific to the ACME protocol. type RemoteError struct { @@ -28,6 +31,12 @@ type TOSError struct { RemoteError } +// NonceError represents the error which is returned if the +// nonce sent by the client was not accepted by the server. +type NonceError struct { + RemoteError +} + type domainError struct { Domain string Error error @@ -73,6 +82,10 @@ func handleHTTPError(resp *http.Response) error { return TOSError{errorDetail} } + if errorDetail.StatusCode == http.StatusBadRequest && strings.HasPrefix(errorDetail.Detail, invalidNonceError) { + return NonceError{errorDetail} + } + return errorDetail } diff --git a/vendor/github.com/xenolf/lego/acme/http.go b/vendor/github.com/xenolf/lego/acme/http.go index 180db786d..dc958046a 100644 --- a/vendor/github.com/xenolf/lego/acme/http.go +++ b/vendor/github.com/xenolf/lego/acme/http.go @@ -31,14 +31,14 @@ const ( func httpHead(url string) (resp *http.Response, err error) { req, err := http.NewRequest("HEAD", url, nil) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to head %q: %v", url, err) } req.Header.Set("User-Agent", userAgent()) resp, err = HTTPClient.Do(req) if err != nil { - return resp, err + return resp, fmt.Errorf("failed to do head %q: %v", url, err) } resp.Body.Close() return resp, err @@ -49,7 +49,7 @@ func httpHead(url string) (resp *http.Response, err error) { func httpPost(url string, bodyType string, body io.Reader) (resp *http.Response, err error) { req, err := http.NewRequest("POST", url, body) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to post %q: %v", url, err) } req.Header.Set("Content-Type", bodyType) req.Header.Set("User-Agent", userAgent()) @@ -62,7 +62,7 @@ func httpPost(url string, bodyType string, body io.Reader) (resp *http.Response, func httpGet(url string) (resp *http.Response, err error) { req, err := http.NewRequest("GET", url, nil) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get %q: %v", url, err) } req.Header.Set("User-Agent", userAgent()) @@ -74,7 +74,7 @@ func httpGet(url string) (resp *http.Response, err error) { func getJSON(uri string, respBody interface{}) (http.Header, error) { resp, err := httpGet(uri) if err != nil { - return nil, fmt.Errorf("failed to get %q: %v", uri, err) + return nil, fmt.Errorf("failed to get json %q: %v", uri, err) } defer resp.Body.Close() diff --git a/vendor/github.com/xenolf/lego/acme/jws.go b/vendor/github.com/xenolf/lego/acme/jws.go index 2a1fc244d..1b4d29d53 100644 --- a/vendor/github.com/xenolf/lego/acme/jws.go +++ b/vendor/github.com/xenolf/lego/acme/jws.go @@ -16,8 +16,7 @@ import ( type jws struct { directoryURL string privKey crypto.PrivateKey - nonces []string - sync.Mutex + nonces nonceManager } func keyAsJWK(key interface{}) *jose.JsonWebKey { @@ -38,19 +37,31 @@ func keyAsJWK(key interface{}) *jose.JsonWebKey { func (j *jws) post(url string, content []byte) (*http.Response, error) { signedContent, err := j.signContent(content) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to sign content -> %s", err.Error()) } resp, err := httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize()))) - if err != nil { - return nil, err + + // Even in case of an error, the response should still contain a nonce. + nonce, nonceErr := getNonceFromResponse(resp) + if nonceErr == nil { + j.nonces.Push(nonce) } - j.Lock() - defer j.Unlock() - j.getNonceFromResponse(resp) + if err != nil { + switch err.(type) { + case NonceError: + // In case of a nonce error - retry once + resp, err = httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize()))) + if err != nil { + return nil, fmt.Errorf("Failed to HTTP POST to %s -> %s", url, err.Error()) + } + default: + return nil, fmt.Errorf("Failed to HTTP POST to %s -> %s", url, err.Error()) + } + } - return resp, err + return resp, nil } func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) { @@ -69,49 +80,63 @@ func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) { signer, err := jose.NewSigner(alg, j.privKey) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to create jose signer -> %s", err.Error()) } signer.SetNonceSource(j) signed, err := signer.Sign(content) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to sign content -> %s", err.Error()) } return signed, nil } -func (j *jws) getNonceFromResponse(resp *http.Response) error { - nonce := resp.Header.Get("Replay-Nonce") - if nonce == "" { - return fmt.Errorf("Server did not respond with a proper nonce header.") +func (j *jws) Nonce() (string, error) { + if nonce, ok := j.nonces.Pop(); ok { + return nonce, nil } - j.nonces = append(j.nonces, nonce) - return nil + return getNonce(j.directoryURL) } -func (j *jws) getNonce() error { - resp, err := httpHead(j.directoryURL) - if err != nil { - return err +type nonceManager struct { + nonces []string + sync.Mutex +} + +func (n *nonceManager) Pop() (string, bool) { + n.Lock() + defer n.Unlock() + + if len(n.nonces) == 0 { + return "", false } - return j.getNonceFromResponse(resp) + nonce := n.nonces[len(n.nonces)-1] + n.nonces = n.nonces[:len(n.nonces)-1] + return nonce, true } -func (j *jws) Nonce() (string, error) { - j.Lock() - defer j.Unlock() - nonce := "" - if len(j.nonces) == 0 { - err := j.getNonce() - if err != nil { - return nonce, err - } +func (n *nonceManager) Push(nonce string) { + n.Lock() + defer n.Unlock() + n.nonces = append(n.nonces, nonce) +} + +func getNonce(url string) (string, error) { + resp, err := httpHead(url) + if err != nil { + return "", fmt.Errorf("Failed to get nonce from HTTP HEAD -> %s", err.Error()) } - if len(j.nonces) == 0 { - return "", fmt.Errorf("Can't get nonce") + + return getNonceFromResponse(resp) +} + +func getNonceFromResponse(resp *http.Response) (string, error) { + nonce := resp.Header.Get("Replay-Nonce") + if nonce == "" { + return "", fmt.Errorf("Server did not respond with a proper nonce header.") } - nonce, j.nonces = j.nonces[len(j.nonces)-1], j.nonces[:len(j.nonces)-1] + return nonce, nil } diff --git a/vendor/github.com/xenolf/lego/providers/http/memcached/memcached.go b/vendor/github.com/xenolf/lego/providers/http/memcached/memcached.go index 9c5f6c0b4..9ac8b811d 100644 --- a/vendor/github.com/xenolf/lego/providers/http/memcached/memcached.go +++ b/vendor/github.com/xenolf/lego/providers/http/memcached/memcached.go @@ -1,4 +1,5 @@ -// Package webroot implements a HTTP provider for solving the HTTP-01 challenge using web server's root path. +// Package memcached implements a HTTP provider for solving the HTTP-01 challenge using memcached +// in combination with a webserver. package memcached import ( |