From 0eeb964534f435413062ff676c72b7ad4894acc2 Mon Sep 17 00:00:00 2001 From: Alberto Bertogli Date: Wed, 1 Mar 2017 00:04:30 +0000 Subject: [PATCH] sts: Limit the size of the HTTPS reads To avoid accidents/DoS when we are fetching a very very large policy, this patch limits the size of the reads to 10k, which should be more than enough for any reasonable policy as per the current draft. --- internal/sts/sts.go | 4 +++- internal/sts/sts_test.go | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/internal/sts/sts.go b/internal/sts/sts.go index 70ebeaf..7a1a4a2 100644 --- a/internal/sts/sts.go +++ b/internal/sts/sts.go @@ -195,7 +195,9 @@ func httpGet(ctx context.Context, url string) ([]byte, error) { defer resp.Body.Close() if resp.StatusCode == http.StatusOK { - return ioutil.ReadAll(resp.Body) + // Read but up to 10k; policies should be way smaller than that, and + // having a limit prevents abuse/accidents with very large replies. + return ioutil.ReadAll(&io.LimitedReader{resp.Body, 10 * 1024}) } return nil, fmt.Errorf("HTTP response status code: %v", resp.StatusCode) } diff --git a/internal/sts/sts_test.go b/internal/sts/sts_test.go index 5ec0877..0b74906 100644 --- a/internal/sts/sts_test.go +++ b/internal/sts/sts_test.go @@ -157,6 +157,22 @@ func TestFetch(t *testing.T) { t.Logf("version99: got expected error: %v", err) } +func TestPolicyTooBig(t *testing.T) { + // Construct a valid but very large JSON as a policy. + raw := `{"version": "STSv1", "mode": "enforce", "mx": [` + for i := 0; i < 2000; i++ { + raw += fmt.Sprintf("\"mx%d\", ", i) + } + raw += `"mxlast"], "max_age": 100}` + policyForDomain["toobig"] = raw + + _, err := Fetch(context.Background(), "toobig") + if err == nil { + t.Errorf("fetch worked, but should have failed") + } + t.Logf("got error as expected: %v", err) +} + // Tests for the policy cache. func mustTempDir(t *testing.T) string {