Example #1
0
// checkRoot determines if the hash, and size are still those reported
// in the snapshot file. It will also check the expiry, however, if the
// hash and size in snapshot are unchanged but the root file has expired,
// there is little expectation that the situation can be remedied.
func (c Client) checkRoot() error {
	role := data.CanonicalRootRole
	size := c.local.Snapshot.Signed.Meta[role].Length

	expectedHashes := c.local.Snapshot.Signed.Meta[role].Hashes

	raw, err := c.cache.GetMeta(data.CanonicalRootRole, size)
	if err != nil {
		return err
	}

	if err := data.CheckHashes(raw, expectedHashes); err != nil {
		return fmt.Errorf("Cached root hashes did not match snapshot root hashes")
	}

	if int64(len(raw)) != size {
		return fmt.Errorf("Cached root size did not match snapshot size")
	}

	root := &data.SignedRoot{}
	err = json.Unmarshal(raw, root)
	if err != nil {
		return ErrCorruptedCache{file: "root.json"}
	}

	if signed.IsExpired(root.Signed.Expires) {
		return tuf.ErrLocalRootExpired{}
	}
	return nil
}
Example #2
0
func (rb *repoBuilder) validateChecksumsFromTimestamp(ts *data.SignedTimestamp) error {
	sn, ok := rb.loadedNotChecksummed[data.CanonicalSnapshotRole]
	if ok {
		// by this point, the SignedTimestamp has been validated so it must have a snapshot hash
		snMeta := ts.Signed.Meta[data.CanonicalSnapshotRole].Hashes
		if err := data.CheckHashes(sn, data.CanonicalSnapshotRole, snMeta); err != nil {
			return err
		}
		delete(rb.loadedNotChecksummed, data.CanonicalSnapshotRole)
	}
	return nil
}
Example #3
0
func (rb *repoBuilder) validateChecksumFor(content []byte, roleName string) error {
	// validate the bootstrap checksum for root, if provided
	if roleName == data.CanonicalRootRole && rb.bootstrappedRootChecksum != nil {
		if err := data.CheckHashes(content, roleName, rb.bootstrappedRootChecksum.Hashes); err != nil {
			return err
		}
	}

	// but we also want to cache the root content, so that when the snapshot is
	// loaded it is validated (to make sure everything in the repo is self-consistent)
	checksums := rb.getChecksumsFor(roleName)
	if checksums != nil { // as opposed to empty, in which case hash check should fail
		if err := data.CheckHashes(content, roleName, *checksums); err != nil {
			return err
		}
	} else if roleName != data.CanonicalTimestampRole {
		// timestamp is the only role which does not need to be checksummed, but
		// for everything else, cache the contents in the list of roles that have
		// not been checksummed by the snapshot/timestamp yet
		rb.loadedNotChecksummed[roleName] = content
	}

	return nil
}
Example #4
0
File: tuf.go Project: cyli/notary
func (t *tufCommander) tufVerify(cmd *cobra.Command, args []string) error {
	if len(args) < 2 {
		cmd.Usage()
		return fmt.Errorf("Must specify a GUN and target")
	}

	config, err := t.configGetter()
	if err != nil {
		return err
	}

	payload, err := getPayload(t)
	if err != nil {
		return err
	}

	gun := args[0]
	targetName := args[1]

	rt, err := getTransport(config, gun, true)
	if err != nil {
		return err
	}

	trustPin, err := getTrustPinning(config)
	if err != nil {
		return err
	}

	nRepo, err := notaryclient.NewNotaryRepository(
		config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever, trustPin)
	if err != nil {
		return err
	}

	target, err := nRepo.GetTargetByName(targetName)
	if err != nil {
		return fmt.Errorf("error retrieving target by name:%s, error:%v", targetName, err)
	}

	if err := data.CheckHashes(payload, targetName, target.Hashes); err != nil {
		return fmt.Errorf("data not present in the trusted collection, %v", err)
	}

	return feedback(t, payload)
}
Example #5
0
func (rb *repoBuilder) validateChecksumsFromSnapshot(sn *data.SignedSnapshot) error {
	var goodRoles []string
	for roleName, loadedBytes := range rb.loadedNotChecksummed {
		switch roleName {
		case data.CanonicalSnapshotRole, data.CanonicalTimestampRole:
			break
		default:
			if err := data.CheckHashes(loadedBytes, roleName, sn.Signed.Meta[roleName].Hashes); err != nil {
				return err
			}
			goodRoles = append(goodRoles, roleName)
		}
	}
	for _, roleName := range goodRoles {
		delete(rb.loadedNotChecksummed, roleName)
	}
	return nil
}
Example #6
0
func (c *Client) downloadSigned(role string, size int64, expectedHashes data.Hashes) ([]byte, *data.Signed, error) {
	rolePath := utils.ConsistentName(role, expectedHashes["sha256"])
	raw, err := c.remote.GetMeta(rolePath, size)
	if err != nil {
		return nil, nil, err
	}

	if expectedHashes != nil {
		if err := data.CheckHashes(raw, expectedHashes); err != nil {
			return nil, nil, ErrChecksumMismatch{role: role}
		}
	}

	s := &data.Signed{}
	err = json.Unmarshal(raw, s)
	if err != nil {
		return nil, nil, err
	}
	return raw, s, nil
}
Example #7
0
// snapshotExpired verifies the checksum(s) for the given snapshot using metadata from the timestamp
func snapshotExpired(ts *data.SignedTimestamp, snapshot []byte) bool {
	// If this check failed, it means the current snapshot was not exactly what we expect
	// via the timestamp. So we can consider it to be "expired."
	return data.CheckHashes(snapshot, data.CanonicalSnapshotRole,
		ts.Signed.Meta[data.CanonicalSnapshotRole].Hashes) != nil
}
Example #8
0
func (c Client) getTargetsFile(role string, snapshotMeta data.Files, consistent bool) (*data.Signed, error) {
	// require role exists in snapshots
	roleMeta, ok := snapshotMeta[role]
	if !ok {
		return nil, data.ErrMissingMeta{Role: role}
	}
	expectedHashes := snapshotMeta[role].Hashes
	if len(expectedHashes) == 0 {
		return nil, data.ErrMissingMeta{Role: role}
	}

	// try to get meta file from content addressed cache
	var download bool
	old := &data.Signed{}
	version := 0
	raw, err := c.cache.GetMeta(role, roleMeta.Length)
	if err != nil || raw == nil {
		logrus.Debugf("Couldn't not find cached %s, must download", role)
		download = true
	} else {
		// file may have been tampered with on disk. Always check the hash!
		if err := data.CheckHashes(raw, expectedHashes); err != nil {
			download = true
		}

		err := json.Unmarshal(raw, old)
		if err == nil {
			targ, err := data.TargetsFromSigned(old, role)
			if err == nil {
				version = targ.Signed.Version
			} else {
				download = true
			}
		} else {
			download = true
		}
	}

	size := snapshotMeta[role].Length
	var s *data.Signed
	if download {
		raw, s, err = c.downloadSigned(role, size, expectedHashes)
		if err != nil {
			return nil, err
		}
	} else {
		logrus.Debug("using cached ", role)
		s = old
	}
	var targetOrDelgRole data.BaseRole
	if data.IsDelegation(role) {
		delgRole, err := c.local.GetDelegationRole(role)
		if err != nil {
			logrus.Debugf("no %s delegation role loaded", role)
			return nil, err
		}
		targetOrDelgRole = delgRole.BaseRole
	} else {
		targetOrDelgRole, err = c.local.GetBaseRole(role)
		if err != nil {
			logrus.Debugf("no %s role loaded", role)
			return nil, err
		}
	}
	if err = signed.Verify(s, targetOrDelgRole, version); err != nil {
		return nil, err
	}
	logrus.Debugf("successfully verified %s", role)
	if download {
		// if we error when setting meta, we should continue.
		err = c.cache.SetMeta(role, raw)
		if err != nil {
			logrus.Errorf("Failed to write %s to local cache: %s", role, err.Error())
		}
	}
	return s, nil
}
Example #9
0
// downloadSnapshot is responsible for downloading the snapshot.json
func (c *Client) downloadSnapshot() error {
	logrus.Debug("Downloading Snapshot...")
	role := data.CanonicalSnapshotRole
	if c.local.Timestamp == nil {
		return tuf.ErrNotLoaded{Role: data.CanonicalTimestampRole}
	}
	size := c.local.Timestamp.Signed.Meta[role].Length
	expectedHashes := c.local.Timestamp.Signed.Meta[role].Hashes
	if len(expectedHashes) == 0 {
		return data.ErrMissingMeta{Role: data.CanonicalSnapshotRole}
	}

	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!
		if err := data.CheckHashes(raw, expectedHashes); err != nil {
			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.SnapshotFromSigned(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, expectedHashes)
		if err != nil {
			return err
		}
	} else {
		logrus.Debug("using cached snapshot")
		s = old
	}

	snapshotRole, err := c.local.GetBaseRole(role)
	if err != nil {
		logrus.Debug("no snapshot role loaded")
		return err
	}
	err = signed.Verify(s, snapshotRole, version)
	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
}
Example #10
0
// downloadRoot is responsible for downloading the root.json
func (c *Client) downloadRoot() error {
	logrus.Debug("Downloading Root...")
	role := data.CanonicalRootRole
	// We can't read an exact size for the root metadata without risking getting stuck in the TUF update cycle
	// since it's possible that downloading timestamp/snapshot metadata may fail due to a signature mismatch
	var size int64 = -1

	// We could not expect what the "snapshot" meta has specified.
	//
	// In some old clients, there is only the "sha256",
	// but both "sha256" and "sha512" in the newer ones.
	//
	// And possibly more in the future.
	var expectedHashes data.Hashes

	if c.local.Snapshot != nil {
		if prevRootMeta, ok := c.local.Snapshot.Signed.Meta[role]; ok {
			size = prevRootMeta.Length
			expectedHashes = prevRootMeta.Hashes
		}
	}

	// if we're bootstrapping we may not have a cached root, an
	// error will result in the "previous root version" being
	// interpreted as 0.
	var download bool
	var err error
	var cachedRoot []byte
	old := &data.Signed{}
	version := 0

	// Due to the same reason, we don't really know how many hashes are there.
	if len(expectedHashes) != 0 {
		// can only trust cache if we have an expected sha256(for example) to trust
		cachedRoot, err = c.cache.GetMeta(role, size)
	}

	if cachedRoot == nil || err != nil {
		logrus.Debug("didn't find a cached root, must download")
		download = true
	} else {
		if err := data.CheckHashes(cachedRoot, expectedHashes); err != nil {
			logrus.Debug("cached root's hash didn't match expected, must download")
			download = true
		}

		err := json.Unmarshal(cachedRoot, old)
		if err == nil {
			root, err := data.RootFromSigned(old)
			if err == nil {
				version = root.Signed.Version
			} else {
				logrus.Debug("couldn't parse Signed part of cached root, must download")
				download = true
			}
		} else {
			logrus.Debug("couldn't parse cached root, must download")
			download = true
		}
	}
	var s *data.Signed
	var raw []byte
	if download {
		// use consistent download if we have the checksum.
		raw, s, err = c.downloadSigned(role, size, expectedHashes)
		if err != nil {
			return err
		}
	} else {
		logrus.Debug("using cached root")
		s = old
	}
	if err := c.verifyRoot(role, s, version); err != nil {
		return err
	}
	if download {
		logrus.Debug("caching downloaded root")
		// Now that we have accepted new root, write it to cache
		if err = c.cache.SetMeta(role, raw); err != nil {
			logrus.Errorf("Failed to write root to local cache: %s", err.Error())
		}
	}
	return nil
}