git » chasquid » commit 0eeb964

sts: Limit the size of the HTTPS reads

author Alberto Bertogli
2017-03-01 00:04:30 UTC
committer Alberto Bertogli
2017-03-01 00:10:10 UTC
parent e66288e4b47410a019ae775376ad775ff5a0f708

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 +3 -1
internal/sts/sts_test.go +16 -0

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 {