Use different limits for metadata downloads
This uses the same limits that python-tuf uses by default
to protect against large downloads. This should eventually
be controlled by the client.
Change-Id: Ie16b0ebd7cc6936e041a909b5d607c8c26cd9a08
diff --git a/client/client.go b/client/client.go
index 9e49269..dcb146b 100644
--- a/client/client.go
+++ b/client/client.go
@@ -12,6 +12,14 @@
"github.com/flynn/go-tuf/verify"
)
+const (
+ // This is the upper limit in bytes we will use to limit the download
+ // size of the root/timestamp roles, since we might not don't know how
+ // big it is.
+ defaultRootDownloadLimit = 512000
+ defaultTimestampDownloadLimit = 16384
+)
+
// LocalStore is local storage for downloaded top-level metadata.
type LocalStore interface {
// GetMeta returns top-level metadata from local storage. The keys are
@@ -91,7 +99,7 @@
if len(rootKeys) < threshold {
return ErrInsufficientKeys
}
- rootJSON, err := c.downloadMetaUnsafe("root.json")
+ rootJSON, err := c.downloadMetaUnsafe("root.json", defaultRootDownloadLimit)
if err != nil {
return err
}
@@ -154,7 +162,7 @@
// Get timestamp.json, extract snapshot.json file meta and save the
// timestamp.json locally
- timestampJSON, err := c.downloadMetaUnsafe("timestamp.json")
+ timestampJSON, err := c.downloadMetaUnsafe("timestamp.json", defaultTimestampDownloadLimit)
if err != nil {
return nil, err
}
@@ -230,7 +238,7 @@
var rootJSON json.RawMessage
var err error
if m == nil {
- rootJSON, err = c.downloadMetaUnsafe("root.json")
+ rootJSON, err = c.downloadMetaUnsafe("root.json", defaultRootDownloadLimit)
} else {
rootJSON, err = c.downloadMetaFromSnapshot("root.json", *m)
}
@@ -328,14 +336,10 @@
}
}
-// maxMetaSize is the maximum number of bytes that will be downloaded when
-// getting remote metadata without knowing it's length.
-const maxMetaSize = 50 * 1024
-
// downloadMetaUnsafe downloads top-level metadata from remote storage without
// verifying it's length and hashes (used for example to download timestamp.json
// which has unknown size). It will download at most maxMetaSize bytes.
-func (c *Client) downloadMetaUnsafe(name string) ([]byte, error) {
+func (c *Client) downloadMetaUnsafe(name string, maxMetaSize int64) ([]byte, error) {
r, size, err := c.remote.GetMeta(name)
if err != nil {
if IsNotFound(err) {
@@ -347,7 +351,7 @@
// return ErrMetaTooLarge if the reported size is greater than maxMetaSize
if size > maxMetaSize {
- return nil, ErrMetaTooLarge{name, size}
+ return nil, ErrMetaTooLarge{name, size, maxMetaSize}
}
// although the size has been checked above, use a LimitReader in case
diff --git a/client/client_test.go b/client/client_test.go
index 911923e..1e6569d 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -230,8 +230,8 @@
func (s *ClientSuite) TestInitRootTooLarge(c *C) {
client := NewClient(MemoryLocalStore(), s.remote)
- s.remote.meta["root.json"] = newFakeFile(make([]byte, maxMetaSize+1))
- c.Assert(client.Init(s.rootKeys(c), 0), Equals, ErrMetaTooLarge{"root.json", maxMetaSize + 1})
+ s.remote.meta["root.json"] = newFakeFile(make([]byte, defaultRootDownloadLimit+1))
+ c.Assert(client.Init(s.rootKeys(c), 0), Equals, ErrMetaTooLarge{"root.json", defaultRootDownloadLimit + 1, defaultRootDownloadLimit})
}
func (s *ClientSuite) TestInitRootExpired(c *C) {
@@ -526,9 +526,9 @@
}
func (s *ClientSuite) TestTimestampTooLarge(c *C) {
- s.remote.meta["timestamp.json"] = newFakeFile(make([]byte, maxMetaSize+1))
+ s.remote.meta["timestamp.json"] = newFakeFile(make([]byte, defaultTimestampDownloadLimit+1))
_, err := s.newClient(c).Update()
- c.Assert(err, Equals, ErrMetaTooLarge{"timestamp.json", maxMetaSize + 1})
+ c.Assert(err, Equals, ErrMetaTooLarge{"timestamp.json", defaultTimestampDownloadLimit + 1, defaultTimestampDownloadLimit})
}
func (s *ClientSuite) TestUpdateLocalRootExpired(c *C) {
diff --git a/client/errors.go b/client/errors.go
index c769d15..fcc17b8 100644
--- a/client/errors.go
+++ b/client/errors.go
@@ -89,12 +89,13 @@
}
type ErrMetaTooLarge struct {
- Name string
- Size int64
+ Name string
+ Size int64
+ MaxSize int64
}
func (e ErrMetaTooLarge) Error() string {
- return fmt.Sprintf("tuf: %s size %d bytes greater than maximum %d bytes", e.Name, e.Size, maxMetaSize)
+ return fmt.Sprintf("tuf: %s size %d bytes greater than maximum %d bytes", e.Name, e.Size, e.MaxSize)
}
type ErrInvalidURL struct {