// downloadTimestamp is responsible for downloading the timestamp.json // Timestamps are special in that we ALWAYS attempt to download and only // use cache if the download fails (and the cache is still valid). func (c *Client) downloadTimestamp() error { logrus.Debug("downloadTimestamp") role := data.RoleName("timestamp") // We may not have a cached timestamp if this is the first time // we're interacting with the repo. This will result in the // version being 0 var download bool old := &data.Signed{} version := 0 cachedTS, err := c.cache.GetMeta(role, maxSize) if err == nil { err := json.Unmarshal(cachedTS, old) if err == nil { ts, err := data.TimestampFromSigned(old) if err == nil { version = ts.Signed.Version } } else { old = nil } } // unlike root, targets and snapshot, always try and download timestamps // from remote, only using the cache one if we couldn't reach remote. raw, s, err := c.downloadSigned(role, maxSize, nil) if err != nil || len(raw) == 0 { if err, ok := err.(store.ErrMetaNotFound); ok { return err } if old == nil { if err == nil { // couldn't retrieve data from server and don't have valid // data in cache. return store.ErrMetaNotFound{} } return err } logrus.Debug("using cached timestamp") s = old } else { download = true } err = signed.Verify(s, role, version, c.keysDB) if err != nil { return err } logrus.Debug("successfully verified timestamp") if download { c.cache.SetMeta(role, raw) } ts, err := data.TimestampFromSigned(s) if err != nil { return err } c.local.SetTimestamp(ts) return nil }
// downloadTimestamp is responsible for downloading the timestamp.json // Timestamps are special in that we ALWAYS attempt to download and only // use cache if the download fails (and the cache is still valid). func (c *Client) downloadTimestamp() error { logrus.Debug("Downloading Timestamp...") role := data.CanonicalTimestampRole // We may not have a cached timestamp if this is the first time // we're interacting with the repo. This will result in the // version being 0 var ( saveToCache bool old *data.Signed version = 0 ) cachedTS, err := c.cache.GetMeta(role, maxSize) if err == nil { cached := &data.Signed{} err := json.Unmarshal(cachedTS, cached) if err == nil { ts, err := data.TimestampFromSigned(cached) if err == nil { version = ts.Signed.Version } old = cached } } // unlike root, targets and snapshot, always try and download timestamps // from remote, only using the cache one if we couldn't reach remote. raw, s, err := c.downloadSigned(role, maxSize, nil) if err != nil || len(raw) == 0 { if old == nil { if err == nil { // couldn't retrieve data from server and don't have valid // data in cache. return store.ErrMetaNotFound{Resource: data.CanonicalTimestampRole} } return err } logrus.Debug(err.Error()) logrus.Warn("Error while downloading remote metadata, using cached timestamp - this might not be the latest version available remotely") s = old } else { saveToCache = true } err = signed.Verify(s, role, version, c.keysDB) if err != nil { return err } logrus.Debug("successfully verified timestamp") if saveToCache { c.cache.SetMeta(role, raw) } ts, err := data.TimestampFromSigned(s) if err != nil { return err } c.local.SetTimestamp(ts) return nil }
func (rb *repoBuilder) loadTimestamp(content []byte, minVersion int, allowExpired bool) error { roleName := data.CanonicalTimestampRole timestampRole, err := rb.repo.Root.BuildBaseRole(roleName) if err != nil { // this should never happen, since it's already been validated return err } signedObj, err := rb.bytesToSignedAndValidateSigs(timestampRole, content) if err != nil { return err } signedTimestamp, err := data.TimestampFromSigned(signedObj) if err != nil { return err } if err := signed.VerifyVersion(&(signedTimestamp.Signed.SignedCommon), minVersion); err != nil { return err } if !allowExpired { // check must go at the end because all other validation should pass if err := signed.VerifyExpiry(&(signedTimestamp.Signed.SignedCommon), roleName); err != nil { return err } } if err := rb.validateChecksumsFromTimestamp(signedTimestamp); err != nil { return err } rb.repo.Timestamp = signedTimestamp return nil }
// verifies that a timestamp is valid, and returned the SignedTimestamp object to add to the tuf repo func (c *Client) verifyTimestamp(s *data.Signed, minVersion int) (*data.SignedTimestamp, error) { timestampRole, err := c.local.GetBaseRole(data.CanonicalTimestampRole) if err != nil { logrus.Debug("no timestamp role loaded") return nil, err } if err := signed.Verify(s, timestampRole, minVersion); err != nil { return nil, err } return data.TimestampFromSigned(s) }
// downloadTimestamp is responsible for downloading the timestamp.json // Timestamps are special in that we ALWAYS attempt to download and only // use cache if the download fails (and the cache is still valid). func (c *Client) downloadTimestamp() error { logrus.Debug("Downloading Timestamp...") role := data.CanonicalTimestampRole // We may not have a cached timestamp if this is the first time // we're interacting with the repo. This will result in the // version being 0 var ( old *data.Signed ts *data.SignedTimestamp version = 0 ) cachedTS, err := c.cache.GetMeta(role, notary.MaxTimestampSize) if err == nil { cached := &data.Signed{} err := json.Unmarshal(cachedTS, cached) if err == nil { ts, err := data.TimestampFromSigned(cached) if err == nil { version = ts.Signed.Version } old = cached } } // unlike root, targets and snapshot, always try and download timestamps // from remote, only using the cache one if we couldn't reach remote. raw, s, err := c.downloadSigned(role, notary.MaxTimestampSize, nil) if err == nil { ts, err = c.verifyTimestamp(s, version) if err == nil { logrus.Debug("successfully verified downloaded timestamp") c.cache.SetMeta(role, raw) c.local.SetTimestamp(ts) return nil } } if old == nil { // couldn't retrieve valid data from server and don't have unmarshallable data in cache. logrus.Debug("no cached timestamp available") return err } logrus.Debug(err.Error()) logrus.Warn("Error while downloading remote metadata, using cached timestamp - this might not be the latest version available remotely") ts, err = c.verifyTimestamp(old, version) if err != nil { return err } logrus.Debug("successfully verified cached timestamp") c.local.SetTimestamp(ts) return nil }
// downloadSnapshot is responsible for downloading the snapshot.json func (c *Client) downloadSnapshot() error { logrus.Debug("downloadSnapshot") role := data.RoleName("snapshot") if c.local.Timestamp == nil { return ErrMissingMeta{role: "snapshot"} } size := c.local.Timestamp.Signed.Meta[role].Length expectedSha256, ok := c.local.Timestamp.Signed.Meta[role].Hashes["sha256"] if !ok { return ErrMissingMeta{role: "snapshot"} } var download bool old := &data.Signed{} version := 0 raw, err := c.cache.GetMeta(role, size) if raw == nil || err != nil { logrus.Debug("no snapshot in cache, must download") download = true } else { // file may have been tampered with on disk. Always check the hash! genHash := sha256.Sum256(raw) if !bytes.Equal(genHash[:], expectedSha256) { logrus.Debug("hash of snapshot in cache did not match expected hash, must download") download = true } err := json.Unmarshal(raw, old) if err == nil { snap, err := data.TimestampFromSigned(old) if err == nil { version = snap.Signed.Version } else { logrus.Debug("Could not parse Signed part of snapshot, must download") download = true } } else { logrus.Debug("Could not parse snapshot, must download") download = true } } var s *data.Signed if download { raw, s, err = c.downloadSigned(role, size, expectedSha256) if err != nil { return err } } else { logrus.Debug("using cached snapshot") s = old } err = signed.Verify(s, role, version, c.keysDB) if err != nil { return err } logrus.Debug("successfully verified snapshot") snap, err := data.SnapshotFromSigned(s) if err != nil { return err } c.local.SetSnapshot(snap) if download { err = c.cache.SetMeta(role, raw) if err != nil { logrus.Errorf("Failed to write snapshot to local cache: %s", err.Error()) } } return nil }
// verifies that a timestamp is valid, and returned the SignedTimestamp object to add to the tuf repo func (c *Client) verifyTimestamp(s *data.Signed, minVersion int, kdb *keys.KeyDB) (*data.SignedTimestamp, error) { if err := signed.Verify(s, data.CanonicalTimestampRole, minVersion, kdb); err != nil { return nil, err } return data.TimestampFromSigned(s) }