Example #1
0
func (s *snapassertsSuite) TestCrossCheckHappy(c *C) {
	digest := makeDigest(12)
	size := uint64(len(fakeSnap(12)))
	headers := map[string]interface{}{
		"snap-id":       "snap-id-1",
		"snap-sha3-384": digest,
		"snap-size":     fmt.Sprintf("%d", size),
		"snap-revision": "12",
		"developer-id":  s.dev1Acct.AccountID(),
		"timestamp":     time.Now().Format(time.RFC3339),
	}
	snapRev, err := s.storeSigning.Sign(asserts.SnapRevisionType, headers, nil, "")
	c.Assert(err, IsNil)
	err = s.localDB.Add(snapRev)
	c.Assert(err, IsNil)

	si := &snap.SideInfo{
		SnapID:   "snap-id-1",
		Revision: snap.R(12),
	}

	// everything cross checks
	err = snapasserts.CrossCheck("foo", digest, size, si, s.localDB)
	c.Check(err, IsNil)
}
Example #2
0
func (s *snapassertsSuite) TestCrossCheckErrors(c *C) {
	digest := makeDigest(12)
	size := uint64(len(fakeSnap(12)))
	headers := map[string]interface{}{
		"snap-id":       "snap-id-1",
		"snap-sha3-384": digest,
		"snap-size":     fmt.Sprintf("%d", size),
		"snap-revision": "12",
		"developer-id":  s.dev1Acct.AccountID(),
		"timestamp":     time.Now().Format(time.RFC3339),
	}
	snapRev, err := s.storeSigning.Sign(asserts.SnapRevisionType, headers, nil, "")
	c.Assert(err, IsNil)
	err = s.localDB.Add(snapRev)
	c.Assert(err, IsNil)

	si := &snap.SideInfo{
		SnapID:   "snap-id-1",
		Revision: snap.R(12),
	}

	// different size
	err = snapasserts.CrossCheck("foo", digest, size+1, si, s.localDB)
	c.Check(err, ErrorMatches, fmt.Sprintf(`snap "foo" file does not have expected size according to signatures \(download is broken or tampered\): %d != %d`, size+1, size))

	// mismatched revision vs what we got from store original info
	err = snapasserts.CrossCheck("foo", digest, size, &snap.SideInfo{
		SnapID:   "snap-id-1",
		Revision: snap.R(21),
	}, s.localDB)
	c.Check(err, ErrorMatches, `snap "foo" does not have expected ID or revision according to assertions \(metadata is broken or tampered\): 21 / snap-id-1 != 12 / snap-id-1`)

	// mismatched snap id vs what we got from store original info
	err = snapasserts.CrossCheck("foo", digest, size, &snap.SideInfo{
		SnapID:   "snap-id-other",
		Revision: snap.R(12),
	}, s.localDB)
	c.Check(err, ErrorMatches, `snap "foo" does not have expected ID or revision according to assertions \(metadata is broken or tampered\): 12 / snap-id-other != 12 / snap-id-1`)

	// changed name
	err = snapasserts.CrossCheck("baz", digest, size, si, s.localDB)
	c.Check(err, ErrorMatches, `cannot install snap "baz" that is undergoing a rename to "foo"`)

}
Example #3
0
// FetchAndCheckSnapAssertions fetches and cross checks the snap assertions matching the given snap file using the provided asserts.Fetcher and assertion database.
func FetchAndCheckSnapAssertions(snapPath string, info *snap.Info, f asserts.Fetcher, db asserts.RODatabase) error {
	sha3_384, size, err := asserts.SnapFileSHA3_384(snapPath)
	if err != nil {
		return err
	}

	if err := snapasserts.FetchSnapAssertions(f, sha3_384); err != nil {
		return fmt.Errorf("cannot fetch snap signatures/assertions: %v", err)
	}

	// cross checks
	return snapasserts.CrossCheck(info.Name(), sha3_384, size, &info.SideInfo, db)
}
Example #4
0
// doValidateSnap fetches the relevant assertions for the snap being installed and cross checks them with the snap.
func doValidateSnap(t *state.Task, _ *tomb.Tomb) error {
	t.State().Lock()
	defer t.State().Unlock()

	ss, err := snapstate.TaskSnapSetup(t)
	if err != nil {
		return nil
	}

	sha3_384, snapSize, err := asserts.SnapFileSHA3_384(ss.SnapPath)
	if err != nil {
		return err
	}

	err = doFetch(t.State(), ss.UserID, func(f asserts.Fetcher) error {
		return snapasserts.FetchSnapAssertions(f, sha3_384)
	})
	if notFound, ok := err.(*store.AssertionNotFoundError); ok {
		if notFound.Ref.Type == asserts.SnapRevisionType {
			return fmt.Errorf("cannot verify snap %q, no matching signatures found", ss.Name())
		} else {
			return fmt.Errorf("cannot find supported signatures to verify snap %q and its hash (%v)", ss.Name(), notFound)
		}
	}
	if err != nil {
		return err
	}

	db := DB(t.State())
	err = snapasserts.CrossCheck(ss.Name(), sha3_384, snapSize, ss.SideInfo, db)
	if err != nil {
		// TODO: trigger a global sanity check
		// that will generate the changes to deal with this
		// for things like snap-decl revocation and renames?
		return err
	}

	// TODO: set DeveloperID from assertions
	return nil
}
Example #5
0
func (s *snapassertsSuite) TestCrossCheckRevokedSnapDecl(c *C) {
	// revoked snap declaration (snap-name=="") !
	headers := map[string]interface{}{
		"series":       "16",
		"snap-id":      "snap-id-1",
		"snap-name":    "",
		"publisher-id": s.dev1Acct.AccountID(),
		"revision":     "1",
		"timestamp":    time.Now().Format(time.RFC3339),
	}
	snapDecl, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
	c.Assert(err, IsNil)
	err = s.localDB.Add(snapDecl)
	c.Assert(err, IsNil)

	digest := makeDigest(12)
	size := uint64(len(fakeSnap(12)))
	headers = map[string]interface{}{
		"snap-id":       "snap-id-1",
		"snap-sha3-384": digest,
		"snap-size":     fmt.Sprintf("%d", size),
		"snap-revision": "12",
		"developer-id":  s.dev1Acct.AccountID(),
		"timestamp":     time.Now().Format(time.RFC3339),
	}
	snapRev, err := s.storeSigning.Sign(asserts.SnapRevisionType, headers, nil, "")
	c.Assert(err, IsNil)
	err = s.localDB.Add(snapRev)
	c.Assert(err, IsNil)

	si := &snap.SideInfo{
		SnapID:   "snap-id-1",
		Revision: snap.R(12),
	}

	err = snapasserts.CrossCheck("foo", digest, size, si, s.localDB)
	c.Check(err, ErrorMatches, `cannot install snap "foo" with a revoked snap declaration`)
}