Пример #1
0
// 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
}
Пример #2
0
// 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
}
Пример #3
0
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
}
Пример #4
0
// 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)
}
Пример #5
0
// 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
}
Пример #6
0
// 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
}
Пример #7
0
// 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)
}