From 661e5e690c3a6a1846d705b2a3847136da1acf36 Mon Sep 17 00:00:00 2001 From: Pavel Forkert Date: Sun, 19 Feb 2017 06:17:22 +0200 Subject: [PATCH] Do not get stuck when server accidentally starts responding with bad data (#349) If `links["next"] == ""` the early return does not send neither success, nor failure to outer code, which leads to whole `getChallenges` method being stuck forever, cause it waits for either `resc` or `errc` to receive message. --- acme/client.go | 1 + acme/client_test.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/acme/client.go b/acme/client.go index e824f508..9afebf11 100644 --- a/acme/client.go +++ b/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 } diff --git a/acme/client_test.go b/acme/client_test.go index c4e3d6a1..b18334c8 100644 --- a/acme/client_test.go +++ b/acme/client_test.go @@ -202,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)