Example #1
0
func (mbss *memBackstoreSuite) TestPutOldRevision(c *C) {
	bs := asserts.NewMemoryBackstore()

	// Create two revisions of assertion.
	a0, err := asserts.Decode([]byte("type: test-only\n" +
		"authority-id: auth-id1\n" +
		"primary-key: foo\n" +
		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" +
		"\n\n" +
		"AXNpZw=="))
	c.Assert(err, IsNil)
	a1, err := asserts.Decode([]byte("type: test-only\n" +
		"authority-id: auth-id1\n" +
		"primary-key: foo\n" +
		"revision: 1\n" +
		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" +
		"\n\n" +
		"AXNpZw=="))
	c.Assert(err, IsNil)

	// Put newer revision, follwed by old revision.
	err = bs.Put(asserts.TestOnlyType, a1)
	c.Assert(err, IsNil)
	err = bs.Put(asserts.TestOnlyType, a0)

	c.Check(err, ErrorMatches, `revision 0 is older than current revision 1`)
	c.Check(err, DeepEquals, &asserts.RevisionError{Current: 1, Used: 0})
}
Example #2
0
func (as *assertsSuite) TestEncoderSingleDecodeOK(c *C) {
	encoded := []byte("type: test-only\n" +
		"authority-id: auth-id2\n" +
		"primary-key: abc\n" +
		"revision: 5\n" +
		"header1: value1\n" +
		"header2: value2\n" +
		"body-length: 8\n" +
		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" +
		"THE-BODY" +
		"\n\n" +
		"AXNpZw==")
	a0, err := asserts.Decode(encoded)
	c.Assert(err, IsNil)
	cont0, _ := a0.Signature()

	stream := new(bytes.Buffer)
	enc := asserts.NewEncoder(stream)
	enc.Encode(a0)

	a1, err := asserts.Decode(stream.Bytes())
	c.Assert(err, IsNil)

	cont1, _ := a1.Signature()
	c.Check(cont1, DeepEquals, cont0)
}
Example #3
0
func (mbss *memBackstoreSuite) TestSearch(c *C) {
	encoded := "type: test-only\n" +
		"authority-id: auth-id1\n" +
		"primary-key: one\n" +
		"other: other1\n" +
		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" +
		"\n\n" +
		"AXNpZw=="
	a1, err := asserts.Decode([]byte(encoded))
	c.Assert(err, IsNil)

	encoded = "type: test-only\n" +
		"authority-id: auth-id1\n" +
		"primary-key: two\n" +
		"other: other2\n" +
		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" +
		"\n\n" +
		"AXNpZw=="
	a2, err := asserts.Decode([]byte(encoded))
	c.Assert(err, IsNil)

	err = mbss.bs.Put(asserts.TestOnlyType, a1)
	c.Assert(err, IsNil)
	err = mbss.bs.Put(asserts.TestOnlyType, a2)
	c.Assert(err, IsNil)

	found := map[string]asserts.Assertion{}
	cb := func(a asserts.Assertion) {
		found[a.HeaderString("primary-key")] = a
	}
	err = mbss.bs.Search(asserts.TestOnlyType, nil, cb, 0)
	c.Assert(err, IsNil)
	c.Check(found, HasLen, 2)

	found = map[string]asserts.Assertion{}
	err = mbss.bs.Search(asserts.TestOnlyType, map[string]string{
		"primary-key": "one",
	}, cb, 0)
	c.Assert(err, IsNil)
	c.Check(found, DeepEquals, map[string]asserts.Assertion{
		"one": a1,
	})

	found = map[string]asserts.Assertion{}
	err = mbss.bs.Search(asserts.TestOnlyType, map[string]string{
		"other": "other2",
	}, cb, 0)
	c.Assert(err, IsNil)
	c.Check(found, DeepEquals, map[string]asserts.Assertion{
		"two": a2,
	})

	found = map[string]asserts.Assertion{}
	err = mbss.bs.Search(asserts.TestOnlyType, map[string]string{
		"primary-key": "two",
		"other":       "other1",
	}, cb, 0)
	c.Assert(err, IsNil)
	c.Check(found, HasLen, 0)
}
Example #4
0
func (fsbss *fsBackstoreSuite) TestGetFormat(c *C) {
	topDir := filepath.Join(c.MkDir(), "asserts-db")
	bs, err := asserts.OpenFSBackstore(topDir)
	c.Assert(err, IsNil)

	af0, err := asserts.Decode([]byte("type: test-only\n" +
		"authority-id: auth-id1\n" +
		"primary-key: foo\n" +
		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" +
		"\n\n" +
		"AXNpZw=="))
	c.Assert(err, IsNil)
	af1, err := asserts.Decode([]byte("type: test-only\n" +
		"authority-id: auth-id1\n" +
		"primary-key: foo\n" +
		"format: 1\n" +
		"revision: 1\n" +
		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" +
		"\n\n" +
		"AXNpZw=="))
	c.Assert(err, IsNil)
	af2, err := asserts.Decode([]byte("type: test-only\n" +
		"authority-id: auth-id1\n" +
		"primary-key: zoo\n" +
		"format: 2\n" +
		"revision: 22\n" +
		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" +
		"\n\n" +
		"AXNpZw=="))
	c.Assert(err, IsNil)

	err = bs.Put(asserts.TestOnlyType, af0)
	c.Assert(err, IsNil)
	err = bs.Put(asserts.TestOnlyType, af1)
	c.Assert(err, IsNil)

	a, err := bs.Get(asserts.TestOnlyType, []string{"foo"}, 1)
	c.Assert(err, IsNil)
	c.Check(a.Revision(), Equals, 1)

	a, err = bs.Get(asserts.TestOnlyType, []string{"foo"}, 0)
	c.Assert(err, IsNil)
	c.Check(a.Revision(), Equals, 0)

	a, err = bs.Get(asserts.TestOnlyType, []string{"zoo"}, 0)
	c.Assert(err, Equals, asserts.ErrNotFound)

	err = bs.Put(asserts.TestOnlyType, af2)
	c.Assert(err, IsNil)

	a, err = bs.Get(asserts.TestOnlyType, []string{"zoo"}, 1)
	c.Assert(err, Equals, asserts.ErrNotFound)

	a, err = bs.Get(asserts.TestOnlyType, []string{"zoo"}, 2)
	c.Assert(err, IsNil)
	c.Check(a.Revision(), Equals, 22)
}
Example #5
0
func init() {
	stagingTrustedAccount, err := asserts.Decode([]byte(encodedStagingTrustedAccount))
	if err != nil {
		panic(fmt.Sprintf("cannot decode trusted assertion: %v", err))
	}
	stagingRootAccountKey, err := asserts.Decode([]byte(encodedStagingRootAccountKey))
	if err != nil {
		panic(fmt.Sprintf("cannot decode trusted assertion: %v", err))
	}
	trustedStagingAssertions = []asserts.Assertion{stagingTrustedAccount, stagingRootAccountKey}
}
Example #6
0
func init() {
	canonicalAccount, err := asserts.Decode([]byte(encodedCanonicalAccount))
	if err != nil {
		panic(fmt.Sprintf("cannot decode trusted assertion: %v", err))
	}
	canonicalRootAccountKey, err := asserts.Decode([]byte(encodedCanonicalRootAccountKey))
	if err != nil {
		panic(fmt.Sprintf("cannot decode trusted assertion: %v", err))
	}
	trustedAssertions = []asserts.Assertion{canonicalAccount, canonicalRootAccountKey}
}
Example #7
0
func (s *systemUserSuite) TestUntilNoModels(c *C) {
	// no models is good for <1y
	su := strings.Replace(s.systemUserStr, s.modelsLine, "", -1)
	_, err := asserts.Decode([]byte(su))
	c.Check(err, IsNil)

	// but invalid for more than one year
	oneYearPlusOne := time.Now().AddDate(1, 0, 1).Truncate(time.Second)
	su = strings.Replace(su, s.untilLine, fmt.Sprintf("until: %s\n", oneYearPlusOne.Format(time.RFC3339)), -1)
	_, err = asserts.Decode([]byte(su))
	c.Check(err, ErrorMatches, systemUserErrPrefix+"'until' time cannot be more than 365 days in the future when no models are specified")
}
Example #8
0
func (mods *modelSuite) TestDecodeStoreIsOptional(c *C) {
	withTimestamp := strings.Replace(modelExample, "TSLINE", mods.tsLine, 1)
	encoded := strings.Replace(withTimestamp, "store: brand-store\n", "store: \n", 1)
	a, err := asserts.Decode([]byte(encoded))
	c.Assert(err, IsNil)
	model := a.(*asserts.Model)
	c.Check(model.Store(), Equals, "")

	encoded = strings.Replace(withTimestamp, "store: brand-store\n", "", 1)
	a, err = asserts.Decode([]byte(encoded))
	c.Assert(err, IsNil)
	model = a.(*asserts.Model)
	c.Check(model.Store(), Equals, "")
}
Example #9
0
func (mods *modelSuite) TestDecodeSystemUserAuthorityIsOptional(c *C) {
	withTimestamp := strings.Replace(modelExample, "TSLINE", mods.tsLine, 1)
	encoded := strings.Replace(withTimestamp, sysUserAuths, "", 1)
	a, err := asserts.Decode([]byte(encoded))
	c.Assert(err, IsNil)
	model := a.(*asserts.Model)
	// the default is just to accept the brand itself
	c.Check(model.SystemUserAuthority(), DeepEquals, []string{"brand-id1"})

	encoded = strings.Replace(withTimestamp, sysUserAuths, "system-user-authority:\n  - foo\n  - bar\n", 1)
	a, err = asserts.Decode([]byte(encoded))
	c.Assert(err, IsNil)
	model = a.(*asserts.Model)
	c.Check(model.SystemUserAuthority(), DeepEquals, []string{"foo", "bar"})
}
Example #10
0
func (s *Store) collectAssertions() (asserts.Backstore, error) {
	bs := asserts.NewMemoryBackstore()

	add := func(a asserts.Assertion) {
		bs.Put(a.Type(), a)
	}

	for _, t := range sysdb.Trusted() {
		add(t)
	}
	add(systestkeys.TestRootAccount)
	add(systestkeys.TestRootAccountKey)
	add(systestkeys.TestStoreAccountKey)

	aFiles, err := filepath.Glob(filepath.Join(s.assertDir, "*"))
	if err != nil {
		return nil, err
	}

	for _, fn := range aFiles {
		b, err := ioutil.ReadFile(fn)
		if err != nil {
			return nil, err
		}

		a, err := asserts.Decode(b)
		if err != nil {
			return nil, err
		}

		add(a)
	}

	return bs, nil
}
Example #11
0
func (s *SnapSignBuildSuite) TestSignBuildWorksDevelGrade(c *C) {
	snapFilename := "foo_1_amd64.snap"
	snapContent := []byte("sample")
	_err := ioutil.WriteFile(snapFilename, snapContent, 0644)
	c.Assert(_err, IsNil)
	defer os.Remove(snapFilename)

	tempdir := c.MkDir()
	for _, fileName := range []string{"pubring.gpg", "secring.gpg", "trustdb.gpg"} {
		data, err := ioutil.ReadFile(filepath.Join("test-data", fileName))
		c.Assert(err, IsNil)
		err = ioutil.WriteFile(filepath.Join(tempdir, fileName), data, 0644)
		c.Assert(err, IsNil)
	}
	os.Setenv("SNAP_GNUPG_HOME", tempdir)
	defer os.Unsetenv("SNAP_GNUPG_HOME")

	_, err := snap.Parser().ParseArgs([]string{"sign-build", snapFilename, "--developer-id", "dev-id1", "--snap-id", "snap-id-1", "--grade", "devel"})
	c.Assert(err, IsNil)
	assertion, err := asserts.Decode([]byte(s.Stdout()))
	c.Assert(err, IsNil)
	c.Check(assertion.Type(), Equals, asserts.SnapBuildType)
	c.Check(assertion.HeaderString("grade"), Equals, "devel")

	// check for valid signature ?!
	c.Check(s.Stderr(), Equals, "")
}
Example #12
0
func decodeModelAssertion(opts *Options) (*asserts.Model, error) {
	fn := opts.ModelFile

	rawAssert, err := ioutil.ReadFile(fn)
	if err != nil {
		return nil, fmt.Errorf("cannot read model assertion: %s", err)
	}

	ass, err := asserts.Decode(rawAssert)
	if err != nil {
		return nil, fmt.Errorf("cannot decode model assertion %q: %s", fn, err)
	}
	modela, ok := ass.(*asserts.Model)
	if !ok {
		return nil, fmt.Errorf("assertion in %q is not a model assertion", fn)
	}

	for _, rsvd := range reserved {
		if modela.Header(rsvd) != nil {
			return nil, fmt.Errorf("model assertion cannot have reserved/unsupported header %q set", rsvd)
		}
	}

	return modela, nil
}
Example #13
0
func (aks *accountKeySuite) TestUntil(c *C) {

	untilSinceLine := "until: " + aks.since.Format(time.RFC3339) + "\n"

	tests := []struct {
		untilLine string
		until     time.Time
	}{
		{"", time.Time{}},           // zero time default
		{aks.untilLine, aks.until},  // in the future
		{untilSinceLine, aks.since}, // same as since
	}

	for _, test := range tests {
		c.Log(test)
		encoded := "type: account-key\n" +
			"authority-id: canonical\n" +
			"account-id: acc-id1\n" +
			"name: default\n" +
			"public-key-sha3-384: " + aks.keyID + "\n" +
			aks.sinceLine +
			test.untilLine +
			fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" +
			"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" +
			aks.pubKeyBody + "\n\n" +
			"openpgp c2ln"
		a, err := asserts.Decode([]byte(encoded))
		c.Assert(err, IsNil)
		accKey := a.(*asserts.AccountKey)
		c.Check(accKey.Until(), Equals, test.until)
	}
}
Example #14
0
func (ss *serialSuite) TestDeviceSessionRequestDecodeInvalid(c *C) {
	tsLine := "timestamp: " + time.Now().Format(time.RFC3339) + "\n"
	encoded := "type: device-session-request\n" +
		"brand-id: brand-id1\n" +
		"model: baz-3000\n" +
		"serial: 99990\n" +
		"nonce: NONCE\n" +
		tsLine +
		"body-length: 0\n" +
		"sign-key-sha3-384: " + ss.deviceKey.PublicKey().ID() + "\n\n" +
		"AXNpZw=="

	invalidTests := []struct{ original, invalid, expectedErr string }{
		{"brand-id: brand-id1\n", "brand-id: \n", `"brand-id" header should not be empty`},
		{"model: baz-3000\n", "model: \n", `"model" header should not be empty`},
		{"serial: 99990\n", "", `"serial" header is mandatory`},
		{"nonce: NONCE\n", "nonce: \n", `"nonce" header should not be empty`},
		{tsLine, "timestamp: 12:30\n", `"timestamp" header is not a RFC3339 date: .*`},
	}

	for _, test := range invalidTests {
		invalid := strings.Replace(encoded, test.original, test.invalid, 1)
		_, err := asserts.Decode([]byte(invalid))
		c.Check(err, ErrorMatches, deviceSessReqErrPrefix+test.expectedErr)
	}
}
Example #15
0
func (aks *accountKeySuite) TestAccountKeyRequestHappy(c *C) {
	akr, err := asserts.SignWithoutAuthority(asserts.AccountKeyRequestType,
		map[string]interface{}{
			"account-id":          "acc-id1",
			"name":                "default",
			"public-key-sha3-384": aks.keyID,
			"since":               aks.since.Format(time.RFC3339),
		}, []byte(aks.pubKeyBody), aks.privKey)
	c.Assert(err, IsNil)

	// roundtrip
	a, err := asserts.Decode(asserts.Encode(akr))
	c.Assert(err, IsNil)

	akr2, ok := a.(*asserts.AccountKeyRequest)
	c.Assert(ok, Equals, true)

	db := aks.openDB(c)
	aks.prereqAccount(c, db)

	err = db.Check(akr2)
	c.Check(err, IsNil)

	c.Check(akr2.AccountID(), Equals, "acc-id1")
	c.Check(akr2.Name(), Equals, "default")
	c.Check(akr2.PublicKeyID(), Equals, aks.keyID)
	c.Check(akr2.Since(), Equals, aks.since)
}
Example #16
0
func (ss *serialSuite) TestSerialRequestDecodeInvalid(c *C) {
	encoded := "type: serial-request\n" +
		"brand-id: brand-id1\n" +
		"model: baz-3000\n" +
		"device-key:\n    DEVICEKEY\n" +
		"request-id: REQID\n" +
		"serial: S\n" +
		"body-length: 2\n" +
		"sign-key-sha3-384: " + ss.deviceKey.PublicKey().ID() + "\n\n" +
		"HW" +
		"\n\n" +
		"AXNpZw=="

	invalidTests := []struct{ original, invalid, expectedErr string }{
		{"brand-id: brand-id1\n", "", `"brand-id" header is mandatory`},
		{"brand-id: brand-id1\n", "brand-id: \n", `"brand-id" header should not be empty`},
		{"model: baz-3000\n", "", `"model" header is mandatory`},
		{"model: baz-3000\n", "model: \n", `"model" header should not be empty`},
		{"request-id: REQID\n", "", `"request-id" header is mandatory`},
		{"request-id: REQID\n", "request-id: \n", `"request-id" header should not be empty`},
		{"device-key:\n    DEVICEKEY\n", "", `"device-key" header is mandatory`},
		{"device-key:\n    DEVICEKEY\n", "device-key: \n", `"device-key" header should not be empty`},
		{"device-key:\n    DEVICEKEY\n", "device-key: $$$\n", `cannot decode public key: .*`},
		{"serial: S\n", "serial:\n  - xyz\n", `"serial" header must be a string`},
	}

	for _, test := range invalidTests {
		invalid := strings.Replace(encoded, test.original, test.invalid, 1)
		invalid = strings.Replace(invalid, "DEVICEKEY", strings.Replace(ss.encodedDevKey, "\n", "\n    ", -1), 1)

		_, err := asserts.Decode([]byte(invalid))
		c.Check(err, ErrorMatches, serialReqErrPrefix+test.expectedErr)
	}
}
Example #17
0
func (mods *modelSuite) TestDecodeInvalid(c *C) {
	encoded := strings.Replace(modelExample, "TSLINE", mods.tsLine, 1)

	invalidTests := []struct{ original, invalid, expectedErr string }{
		{"series: 16\n", "", `"series" header is mandatory`},
		{"series: 16\n", "series: \n", `"series" header should not be empty`},
		{"brand-id: brand-id1\n", "", `"brand-id" header is mandatory`},
		{"brand-id: brand-id1\n", "brand-id: \n", `"brand-id" header should not be empty`},
		{"brand-id: brand-id1\n", "brand-id: random\n", `authority-id and brand-id must match, model assertions are expected to be signed by the brand: "brand-id1" != "random"`},
		{"model: baz-3000\n", "", `"model" header is mandatory`},
		{"model: baz-3000\n", "model: \n", `"model" header should not be empty`},
		{"model: baz-3000\n", "model: baz/3000\n", `"model" primary key header cannot contain '/'`},
		{"architecture: amd64\n", "", `"architecture" header is mandatory`},
		{"architecture: amd64\n", "architecture: \n", `"architecture" header should not be empty`},
		{"gadget: brand-gadget\n", "", `"gadget" header is mandatory`},
		{"gadget: brand-gadget\n", "gadget: \n", `"gadget" header should not be empty`},
		{"kernel: baz-linux\n", "", `"kernel" header is mandatory`},
		{"kernel: baz-linux\n", "kernel: \n", `"kernel" header should not be empty`},
		{"store: brand-store\n", "store:\n  - xyz\n", `"store" header must be a string`},
		{mods.tsLine, "", `"timestamp" header is mandatory`},
		{mods.tsLine, "timestamp: \n", `"timestamp" header should not be empty`},
		{mods.tsLine, "timestamp: 12:30\n", `"timestamp" header is not a RFC3339 date: .*`},
		{reqSnaps, "required-snaps: foo\n", `"required-snaps" header must be a list of strings`},
		{reqSnaps, "required-snaps:\n  -\n    - nested\n", `"required-snaps" header must be a list of strings`},
	}

	for _, test := range invalidTests {
		invalid := strings.Replace(encoded, test.original, test.invalid, 1)
		_, err := asserts.Decode([]byte(invalid))
		c.Check(err, ErrorMatches, modelErrPrefix+test.expectedErr)
	}
}
Example #18
0
func (srs *snapRevSuite) TestDecodeInvalid(c *C) {
	encoded := srs.makeValidEncoded()

	digestHdr := "snap-sha3-384: " + blobSHA3_384 + "\n"
	invalidTests := []struct{ original, invalid, expectedErr string }{
		{"snap-id: snap-id-1\n", "", `"snap-id" header is mandatory`},
		{"snap-id: snap-id-1\n", "snap-id: \n", `"snap-id" header should not be empty`},
		{digestHdr, "", `"snap-sha3-384" header is mandatory`},
		{digestHdr, "snap-sha3-384: \n", `"snap-sha3-384" header should not be empty`},
		{digestHdr, "snap-sha3-384: #\n", `"snap-sha3-384" header cannot be decoded:.*`},
		{digestHdr, "snap-sha3-384: eHl6\n", `"snap-sha3-384" header does not have the expected bit length: 24`},
		{"snap-size: 123\n", "", `"snap-size" header is mandatory`},
		{"snap-size: 123\n", "snap-size: \n", `"snap-size" header should not be empty`},
		{"snap-size: 123\n", "snap-size: -1\n", `"snap-size" header is not an unsigned integer: -1`},
		{"snap-size: 123\n", "snap-size: zzz\n", `"snap-size" header is not an unsigned integer: zzz`},
		{"snap-revision: 1\n", "", `"snap-revision" header is mandatory`},
		{"snap-revision: 1\n", "snap-revision: \n", `"snap-revision" header should not be empty`},
		{"snap-revision: 1\n", "snap-revision: -1\n", `"snap-revision" header must be >=1: -1`},
		{"snap-revision: 1\n", "snap-revision: 0\n", `"snap-revision" header must be >=1: 0`},
		{"snap-revision: 1\n", "snap-revision: zzz\n", `"snap-revision" header is not an integer: zzz`},
		{"developer-id: dev-id1\n", "", `"developer-id" header is mandatory`},
		{"developer-id: dev-id1\n", "developer-id: \n", `"developer-id" header should not be empty`},
		{srs.tsLine, "", `"timestamp" header is mandatory`},
		{srs.tsLine, "timestamp: \n", `"timestamp" header should not be empty`},
		{srs.tsLine, "timestamp: 12:30\n", `"timestamp" header is not a RFC3339 date: .*`},
	}

	for _, test := range invalidTests {
		invalid := strings.Replace(encoded, test.original, test.invalid, 1)
		_, err := asserts.Decode([]byte(invalid))
		c.Check(err, ErrorMatches, snapRevErrPrefix+test.expectedErr)
	}
}
Example #19
0
func (aks *accountKeySuite) TestAccountKeyRequestUntil(c *C) {
	db := aks.openDB(c)
	aks.prereqAccount(c, db)

	tests := []struct {
		untilHeader string
		until       time.Time
	}{
		{"", time.Time{}},                           // zero time default
		{aks.until.Format(time.RFC3339), aks.until}, // in the future
		{aks.since.Format(time.RFC3339), aks.since}, // same as since
	}

	for _, test := range tests {
		c.Log(test)
		headers := map[string]interface{}{
			"account-id":          "acc-id1",
			"name":                "default",
			"public-key-sha3-384": aks.keyID,
			"since":               aks.since.Format(time.RFC3339),
		}
		if test.untilHeader != "" {
			headers["until"] = test.untilHeader
		}
		akr, err := asserts.SignWithoutAuthority(asserts.AccountKeyRequestType, headers, []byte(aks.pubKeyBody), aks.privKey)
		c.Assert(err, IsNil)
		a, err := asserts.Decode(asserts.Encode(akr))
		c.Assert(err, IsNil)
		akr2 := a.(*asserts.AccountKeyRequest)
		c.Check(akr2.Until(), Equals, test.until)
		err = db.Check(akr2)
		c.Check(err, IsNil)
	}
}
Example #20
0
func (s *baseDeclSuite) TestDecodeInvalid(c *C) {
	tsLine := "timestamp: 2016-09-29T19:50:49Z\n"

	encoded := "type: base-declaration\n" +
		"authority-id: canonical\n" +
		"series: 16\n" +
		"plugs:\n  interface1: true\n" +
		"slots:\n  interface2: true\n" +
		tsLine +
		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" +
		"\n\n" +
		"AXNpZw=="

	invalidTests := []struct{ original, invalid, expectedErr string }{
		{"series: 16\n", "", `"series" header is mandatory`},
		{"series: 16\n", "series: \n", `"series" header should not be empty`},
		{"plugs:\n  interface1: true\n", "plugs: \n", `"plugs" header must be a map`},
		{"plugs:\n  interface1: true\n", "plugs:\n  intf1:\n    foo: bar\n", `plug rule for interface "intf1" must specify at least one of.*`},
		{"slots:\n  interface2: true\n", "slots: \n", `"slots" header must be a map`},
		{"slots:\n  interface2: true\n", "slots:\n  intf1:\n    foo: bar\n", `slot rule for interface "intf1" must specify at least one of.*`},
		{tsLine, "", `"timestamp" header is mandatory`},
		{tsLine, "timestamp: 12:30\n", `"timestamp" header is not a RFC3339 date: .*`},
	}

	for _, test := range invalidTests {
		invalid := strings.Replace(encoded, test.original, test.invalid, 1)
		_, err := asserts.Decode([]byte(invalid))
		c.Check(err, ErrorMatches, baseDeclErrPrefix+test.expectedErr)
	}

}
Example #21
0
func (mods *modelSuite) TestDecodeDisplayNameIsOptional(c *C) {
	withTimestamp := strings.Replace(modelExample, "TSLINE", mods.tsLine, 1)
	encoded := strings.Replace(withTimestamp, "display-name: Baz 3000\n", "display-name: \n", 1)
	a, err := asserts.Decode([]byte(encoded))
	c.Assert(err, IsNil)
	model := a.(*asserts.Model)
	// optional but we fallback to Model
	c.Check(model.DisplayName(), Equals, "baz-3000")

	encoded = strings.Replace(withTimestamp, "display-name: Baz 3000\n", "", 1)
	a, err = asserts.Decode([]byte(encoded))
	c.Assert(err, IsNil)
	model = a.(*asserts.Model)
	// optional but we fallback to Model
	c.Check(model.DisplayName(), Equals, "baz-3000")
}
Example #22
0
func (aks *accountKeySuite) TestAccountKeyRequestDecodeInvalidPublicKey(c *C) {
	headers := "type: account-key-request\n" +
		"account-id: acc-id1\n" +
		"name: default\n" +
		"public-key-sha3-384: " + aks.keyID + "\n" +
		aks.sinceLine +
		aks.untilLine

	raw, err := base64.StdEncoding.DecodeString(aks.pubKeyBody)
	c.Assert(err, IsNil)
	spurious := base64.StdEncoding.EncodeToString(append(raw, "gorp"...))

	invalidPublicKeyTests := []struct{ body, expectedErr string }{
		{"", "cannot decode public key: no data"},
		{"==", "cannot decode public key: .*"},
		{"stuff", "cannot decode public key: .*"},
		{"AnNpZw==", "unsupported public key format version: 2"},
		{"AUJST0tFTg==", "cannot decode public key: .*"},
		{spurious, "public key has spurious trailing data"},
	}

	for _, test := range invalidPublicKeyTests {
		invalid := headers +
			fmt.Sprintf("body-length: %v", len(test.body)) + "\n" +
			"sign-key-sha3-384: " + aks.privKey.PublicKey().ID() + "\n\n" +
			test.body + "\n\n" +
			"AXNpZw=="

		_, err := asserts.Decode([]byte(invalid))
		c.Check(err, ErrorMatches, accKeyReqErrPrefix+test.expectedErr)
	}
}
Example #23
0
func (s *SnapSignBuildSuite) TestSignBuildWorks(c *C) {
	snapFilename := "foo_1_amd64.snap"
	snapContent := []byte("sample")
	_err := ioutil.WriteFile(snapFilename, snapContent, 0644)
	c.Assert(_err, IsNil)
	defer os.Remove(snapFilename)

	tempdir := c.MkDir()
	for _, fileName := range []string{"pubring.gpg", "secring.gpg", "trustdb.gpg"} {
		data, err := ioutil.ReadFile(filepath.Join("test-data", fileName))
		c.Assert(err, IsNil)
		err = ioutil.WriteFile(filepath.Join(tempdir, fileName), data, 0644)
		c.Assert(err, IsNil)
	}
	os.Setenv("SNAP_GNUPG_HOME", tempdir)
	defer os.Unsetenv("SNAP_GNUPG_HOME")

	_, err := snap.Parser().ParseArgs([]string{"sign-build", snapFilename, "--developer-id", "dev-id1", "--snap-id", "snap-id-1"})
	c.Assert(err, IsNil)

	assertion, err := asserts.Decode([]byte(s.Stdout()))
	c.Assert(err, IsNil)
	c.Check(assertion.Type(), Equals, asserts.SnapBuildType)
	c.Check(assertion.Revision(), Equals, 0)
	c.Check(assertion.HeaderString("authority-id"), Equals, "dev-id1")
	c.Check(assertion.HeaderString("developer-id"), Equals, "dev-id1")
	c.Check(assertion.HeaderString("grade"), Equals, "stable")
	c.Check(assertion.HeaderString("snap-id"), Equals, "snap-id-1")
	c.Check(assertion.HeaderString("snap-size"), Equals, fmt.Sprintf("%d", len(snapContent)))
	c.Check(assertion.HeaderString("snap-sha3-384"), Equals, "jyP7dUgb8HiRNd1SdYPp_il-YNrl6P6PgNAe-j6_7WytjKslENhMD3Of5XBU5bQK")

	// check for valid signature ?!
	c.Check(s.Stderr(), Equals, "")
}
Example #24
0
func (ss *serialSuite) TestDeviceSessionRequest(c *C) {
	ts := time.Now().UTC().Round(time.Second)
	sessReq, err := asserts.SignWithoutAuthority(asserts.DeviceSessionRequestType,
		map[string]interface{}{
			"brand-id":  "brand-id1",
			"model":     "baz-3000",
			"serial":    "99990",
			"nonce":     "NONCE",
			"timestamp": ts.Format(time.RFC3339),
		}, nil, ss.deviceKey)
	c.Assert(err, IsNil)

	// roundtrip
	a, err := asserts.Decode(asserts.Encode(sessReq))
	c.Assert(err, IsNil)

	sessReq2, ok := a.(*asserts.DeviceSessionRequest)
	c.Assert(ok, Equals, true)

	// standalone signature check
	err = asserts.SignatureCheck(sessReq2, ss.deviceKey.PublicKey())
	c.Check(err, IsNil)

	c.Check(sessReq2.BrandID(), Equals, "brand-id1")
	c.Check(sessReq2.Model(), Equals, "baz-3000")
	c.Check(sessReq2.Serial(), Equals, "99990")
	c.Check(sessReq2.Nonce(), Equals, "NONCE")
	c.Check(sessReq2.Timestamp().Equal(ts), Equals, true)
}
Example #25
0
func (s *SnapKeysSuite) TestExportKeyAccount(c *C) {
	rootPrivKey, _ := assertstest.GenerateKey(1024)
	storePrivKey, _ := assertstest.GenerateKey(752)
	storeSigning := assertstest.NewStoreStack("canonical", rootPrivKey, storePrivKey)
	manager := asserts.NewGPGKeypairManager()
	assertstest.NewAccount(storeSigning, "developer1", nil, "")
	rest, err := snap.Parser().ParseArgs([]string{"export-key", "another", "--account=developer1"})
	c.Assert(err, IsNil)
	c.Assert(rest, DeepEquals, []string{})
	assertion, err := asserts.Decode(s.stdout.Bytes())
	c.Assert(err, IsNil)
	c.Check(assertion.Type(), Equals, asserts.AccountKeyRequestType)
	c.Check(assertion.Revision(), Equals, 0)
	c.Check(assertion.HeaderString("account-id"), Equals, "developer1")
	c.Check(assertion.HeaderString("name"), Equals, "another")
	c.Check(assertion.HeaderString("public-key-sha3-384"), Equals, "DVQf1U4mIsuzlQqAebjjTPYtYJ-GEhJy0REuj3zvpQYTZ7EJj7adBxIXLJ7Vmk3L")
	since, err := time.Parse(time.RFC3339, assertion.HeaderString("since"))
	c.Assert(err, IsNil)
	zone, offset := since.Zone()
	c.Check(zone, Equals, "UTC")
	c.Check(offset, Equals, 0)
	c.Check(s.Stderr(), Equals, "")
	privKey, err := manager.Get(assertion.HeaderString("public-key-sha3-384"))
	c.Assert(err, IsNil)
	err = asserts.SignatureCheck(assertion, privKey.PublicKey())
	c.Assert(err, IsNil)
}
Example #26
0
func (chks *checkSuite) TestCheckForgery(c *C) {
	trustedKey := testPrivKey0

	cfg := &asserts.DatabaseConfig{
		Backstore: chks.bs,
		Trusted:   []asserts.Assertion{asserts.BootstrapAccountKeyForTest("canonical", trustedKey.PublicKey())},
	}
	db, err := asserts.OpenDatabase(cfg)
	c.Assert(err, IsNil)

	encoded := asserts.Encode(chks.a)
	content, encodedSig := chks.a.Signature()
	// forgery
	forgedSig := new(packet.Signature)
	forgedSig.PubKeyAlgo = packet.PubKeyAlgoRSA
	forgedSig.Hash = crypto.SHA512
	forgedSig.CreationTime = time.Now()
	h := crypto.SHA512.New()
	h.Write(content)
	pk1 := packet.NewRSAPrivateKey(time.Unix(1, 0), testPrivKey1RSA)
	err = forgedSig.Sign(h, pk1, &packet.Config{DefaultHash: crypto.SHA512})
	c.Assert(err, IsNil)
	buf := new(bytes.Buffer)
	forgedSig.Serialize(buf)
	b := append([]byte{0x1}, buf.Bytes()...)
	forgedSigEncoded := base64.StdEncoding.EncodeToString(b)
	forgedEncoded := bytes.Replace(encoded, encodedSig, []byte(forgedSigEncoded), 1)
	c.Assert(forgedEncoded, Not(DeepEquals), encoded)

	forgedAssert, err := asserts.Decode(forgedEncoded)
	c.Assert(err, IsNil)

	err = db.Check(forgedAssert)
	c.Assert(err, ErrorMatches, "failed signature verification: .*")
}
Example #27
0
func (sds *snapDeclSuite) TestDecodeOK(c *C) {
	encoded := "type: snap-declaration\n" +
		"authority-id: canonical\n" +
		"series: 16\n" +
		"snap-id: snap-id-1\n" +
		"snap-name: first\n" +
		"publisher-id: dev-id1\n" +
		"refresh-control:\n  - foo\n  - bar\n" +
		"auto-aliases:\n  - cmd1\n  - cmd_2\n  - Cmd-3\n  - CMD.4\n" +
		sds.tsLine +
		"body-length: 0\n" +
		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" +
		"\n\n" +
		"AXNpZw=="
	a, err := asserts.Decode([]byte(encoded))
	c.Assert(err, IsNil)
	c.Check(a.Type(), Equals, asserts.SnapDeclarationType)
	snapDecl := a.(*asserts.SnapDeclaration)
	c.Check(snapDecl.AuthorityID(), Equals, "canonical")
	c.Check(snapDecl.Timestamp(), Equals, sds.ts)
	c.Check(snapDecl.Series(), Equals, "16")
	c.Check(snapDecl.SnapID(), Equals, "snap-id-1")
	c.Check(snapDecl.SnapName(), Equals, "first")
	c.Check(snapDecl.PublisherID(), Equals, "dev-id1")
	c.Check(snapDecl.RefreshControl(), DeepEquals, []string{"foo", "bar"})
	c.Check(snapDecl.AutoAliases(), DeepEquals, []string{"cmd1", "cmd_2", "Cmd-3", "CMD.4"})
}
Example #28
0
func (ss *serialSuite) TestDecodeInvalid(c *C) {
	encoded := strings.Replace(serialExample, "TSLINE", ss.tsLine, 1)

	invalidTests := []struct{ original, invalid, expectedErr string }{
		{"brand-id: brand-id1\n", "", `"brand-id" header is mandatory`},
		{"brand-id: brand-id1\n", "brand-id: \n", `"brand-id" header should not be empty`},
		{"authority-id: brand-id1\n", "authority-id: random\n", `authority-id and brand-id must match, serial assertions are expected to be signed by the brand: "random" != "brand-id1"`},
		{"model: baz-3000\n", "", `"model" header is mandatory`},
		{"model: baz-3000\n", "model: \n", `"model" header should not be empty`},
		{"serial: 2700\n", "", `"serial" header is mandatory`},
		{"serial: 2700\n", "serial: \n", `"serial" header should not be empty`},
		{ss.tsLine, "", `"timestamp" header is mandatory`},
		{ss.tsLine, "timestamp: \n", `"timestamp" header should not be empty`},
		{ss.tsLine, "timestamp: 12:30\n", `"timestamp" header is not a RFC3339 date: .*`},
		{"device-key:\n    DEVICEKEY\n", "", `"device-key" header is mandatory`},
		{"device-key:\n    DEVICEKEY\n", "device-key: \n", `"device-key" header should not be empty`},
		{"device-key:\n    DEVICEKEY\n", "device-key: $$$\n", `cannot decode public key: .*`},
		{"device-key-sha3-384: KEYID\n", "", `"device-key-sha3-384" header is mandatory`},
	}

	for _, test := range invalidTests {
		invalid := strings.Replace(encoded, test.original, test.invalid, 1)
		invalid = strings.Replace(invalid, "DEVICEKEY", strings.Replace(ss.encodedDevKey, "\n", "\n    ", -1), 1)
		invalid = strings.Replace(invalid, "KEYID", ss.deviceKey.PublicKey().ID(), 1)
		_, err := asserts.Decode([]byte(invalid))
		c.Check(err, ErrorMatches, serialErrPrefix+test.expectedErr)
	}
}
Example #29
0
func (vs *validationSuite) TestDecodeInvalid(c *C) {
	encoded := vs.makeValidEncoded()

	invalidTests := []struct{ original, invalid, expectedErr string }{
		{"series: 16\n", "", `"series" header is mandatory`},
		{"series: 16\n", "series: \n", `"series" header should not be empty`},
		{"snap-id: snap-id-1\n", "", `"snap-id" header is mandatory`},
		{"snap-id: snap-id-1\n", "snap-id: \n", `"snap-id" header should not be empty`},
		{"approved-snap-id: snap-id-2\n", "", `"approved-snap-id" header is mandatory`},
		{"approved-snap-id: snap-id-2\n", "approved-snap-id: \n", `"approved-snap-id" header should not be empty`},
		{"approved-snap-revision: 42\n", "", `"approved-snap-revision" header is mandatory`},
		{"approved-snap-revision: 42\n", "approved-snap-revision: z\n", `"approved-snap-revision" header is not an integer: z`},
		{"approved-snap-revision: 42\n", "approved-snap-revision: 0\n", `"approved-snap-revision" header must be >=1: 0`},
		{"approved-snap-revision: 42\n", "approved-snap-revision: -1\n", `"approved-snap-revision" header must be >=1: -1`},
		{vs.tsLine, "", `"timestamp" header is mandatory`},
		{vs.tsLine, "timestamp: \n", `"timestamp" header should not be empty`},
		{vs.tsLine, "timestamp: 12:30\n", `"timestamp" header is not a RFC3339 date: .*`},
	}

	for _, test := range invalidTests {
		invalid := strings.Replace(encoded, test.original, test.invalid, 1)
		_, err := asserts.Decode([]byte(invalid))
		c.Check(err, ErrorMatches, validationErrPrefix+test.expectedErr)
	}
}
Example #30
0
func (ss *serialSuite) TestSerialRequestHappy(c *C) {
	sreq, err := asserts.SignWithoutAuthority(asserts.SerialRequestType,
		map[string]interface{}{
			"brand-id":   "brand-id1",
			"model":      "baz-3000",
			"device-key": ss.encodedDevKey,
			"request-id": "REQID",
		}, []byte("HW-DETAILS"), ss.deviceKey)
	c.Assert(err, IsNil)

	// roundtrip
	a, err := asserts.Decode(asserts.Encode(sreq))
	c.Assert(err, IsNil)

	sreq2, ok := a.(*asserts.SerialRequest)
	c.Assert(ok, Equals, true)

	// standalone signature check
	err = asserts.SignatureCheck(sreq2, sreq2.DeviceKey())
	c.Check(err, IsNil)

	c.Check(sreq2.BrandID(), Equals, "brand-id1")
	c.Check(sreq2.Model(), Equals, "baz-3000")
	c.Check(sreq2.RequestID(), Equals, "REQID")

	c.Check(sreq2.Serial(), Equals, "")
}