mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 18:48:08 +00:00 
			
		
		
		
	Merge pull request #2108 from hashicorp/f-req-size-limit
http: limit maximum request size
This commit is contained in:
		| @@ -26,6 +26,11 @@ const ( | |||||||
| 	// NoRequestForwardingHeaderName is the name of the header telling Vault | 	// NoRequestForwardingHeaderName is the name of the header telling Vault | ||||||
| 	// not to use request forwarding | 	// not to use request forwarding | ||||||
| 	NoRequestForwardingHeaderName = "X-Vault-No-Request-Forwarding" | 	NoRequestForwardingHeaderName = "X-Vault-No-Request-Forwarding" | ||||||
|  |  | ||||||
|  | 	// MaxRequestSize is the maximum accepted request size. This is to prevent | ||||||
|  | 	// a denial of service attack where no Content-Length is provided and the server | ||||||
|  | 	// is fed ever more data until it exhausts memory. | ||||||
|  | 	MaxRequestSize = 32 * 1024 * 1024 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Handler returns an http.Handler for the API. This can be used on | // Handler returns an http.Handler for the API. This can be used on | ||||||
| @@ -109,7 +114,10 @@ func stripPrefix(prefix, path string) (string, bool) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func parseRequest(r *http.Request, out interface{}) error { | func parseRequest(r *http.Request, out interface{}) error { | ||||||
| 	err := jsonutil.DecodeJSONFromReader(r.Body, out) | 	// Limit the maximum number of bytes to MaxRequestSize to protect | ||||||
|  | 	// against an indefinite amount of data being read. | ||||||
|  | 	limit := &io.LimitedReader{R: r.Body, N: MaxRequestSize} | ||||||
|  | 	err := jsonutil.DecodeJSONFromReader(limit, out) | ||||||
| 	if err != nil && err != io.EOF { | 	if err != nil && err != io.EOF { | ||||||
| 		return fmt.Errorf("Failed to parse JSON input: %s", err) | 		return fmt.Errorf("Failed to parse JSON input: %s", err) | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -26,6 +26,11 @@ func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Reques | |||||||
| 		return nil, http.StatusNotFound, nil | 		return nil, http.StatusNotFound, nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Verify the content length does not exceed the maximum size | ||||||
|  | 	if r.ContentLength >= MaxRequestSize { | ||||||
|  | 		return nil, http.StatusRequestEntityTooLarge, nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// Determine the operation | 	// Determine the operation | ||||||
| 	var op logical.Operation | 	var op logical.Operation | ||||||
| 	switch r.Method { | 	switch r.Method { | ||||||
|   | |||||||
| @@ -231,3 +231,16 @@ func TestLogical_RawHTTP(t *testing.T) { | |||||||
| 		t.Fatalf("Bad: %s", body.Bytes()) | 		t.Fatalf("Bad: %s", body.Bytes()) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestLogical_RequestSizeLimit(t *testing.T) { | ||||||
|  | 	core, _, token := vault.TestCoreUnsealed(t) | ||||||
|  | 	ln, addr := TestServer(t, core) | ||||||
|  | 	defer ln.Close() | ||||||
|  | 	TestServerAuth(t, addr, token) | ||||||
|  |  | ||||||
|  | 	// Write a very large object, should fail | ||||||
|  | 	resp := testHttpPut(t, token, addr+"/v1/secret/foo", map[string]interface{}{ | ||||||
|  | 		"data": make([]byte, MaxRequestSize), | ||||||
|  | 	}) | ||||||
|  | 	testResponseStatus(t, resp, 413) | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Armon Dadgar
					Armon Dadgar