2015-11-10 18:33:36 +01:00
// -*- Mode: Go; indent-tabs-mode: t -*-
/ *
2024-02-07 10:16:09 +01:00
* Copyright ( C ) 2015 - 2024 Canonical Ltd
2015-11-10 18:33:36 +01:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*
* /
package asserts
import (
2016-01-27 21:21:11 +01:00
"bufio"
2015-11-10 18:33:36 +01:00
"bytes"
2016-08-01 23:10:40 +02:00
"crypto"
2024-03-13 15:22:05 +00:00
"encoding/json"
2015-11-10 18:33:36 +01:00
"fmt"
2016-01-22 18:47:51 +01:00
"io"
2024-03-13 15:22:05 +00:00
"reflect"
2015-11-18 18:08:59 +01:00
"sort"
2015-11-10 18:33:36 +01:00
"strconv"
2016-08-16 13:03:03 +02:00
"strings"
2016-08-25 11:36:59 +02:00
"unicode/utf8"
2022-02-26 18:58:47 +01:00
"github.com/snapcore/snapd/osutil"
2022-07-06 15:33:09 +02:00
"github.com/snapcore/snapd/snap/naming"
2015-11-10 18:33:36 +01:00
)
2016-07-29 18:14:18 +02:00
type typeFlags int
const (
2020-06-11 18:10:55 +02:00
noAuthority typeFlags = 1 << iota
sequenceForming
2024-03-13 15:22:05 +00:00
jsonBody
2016-07-29 18:14:18 +02:00
)
2019-08-09 16:18:46 -05:00
// MetaHeaders is a list of headers in assertions which are about the assertion
// itself.
2019-08-20 09:56:16 -05:00
var MetaHeaders = [ ... ] string {
2019-08-09 16:18:46 -05:00
"type" ,
"format" ,
"authority-id" ,
"revision" ,
"body-length" ,
"sign-key-sha3-384" ,
}
2016-01-20 20:22:00 +01:00
// AssertionType describes a known assertion type with its name and metadata.
type AssertionType struct {
2016-01-20 21:29:00 +01:00
// Name of the type.
Name string
// PrimaryKey holds the names of the headers that constitute the
// unique primary key for this assertion type.
2016-01-20 20:44:45 +01:00
PrimaryKey [ ] string
2022-02-17 18:29:50 +01:00
// OptionalPrimaryKeyDefaults holds the default values for
// optional primary key headers.
// Optional primary key headers can be added to types defined
// in previous versions of snapd, as long as they are added at
// the end of the old primary key together with a default value set in
2022-04-05 10:04:48 +02:00
// this map. So they must form a contiguous suffix of PrimaryKey with
// each member having a default value set in this map.
// Optional primary key headers are not supported for sequence
// forming types.
2022-02-17 18:29:50 +01:00
OptionalPrimaryKeyDefaults map [ string ] string
2016-01-21 10:11:32 +01:00
2016-01-21 10:20:06 +01:00
assembler func ( assert assertionBase ) ( Assertion , error )
2016-07-29 18:14:18 +02:00
flags typeFlags
2016-01-20 20:22:00 +01:00
}
2015-11-10 18:33:36 +01:00
2022-02-17 18:29:50 +01:00
func ( at * AssertionType ) validate ( ) {
if len ( at . OptionalPrimaryKeyDefaults ) != 0 && at . flags & sequenceForming != 0 {
panic ( fmt . Sprintf ( "assertion type %q cannot be both sequence forming and have optional primary keys" , at . Name ) )
}
noptional := 0
for _ , k := range at . PrimaryKey {
defl := at . OptionalPrimaryKeyDefaults [ k ]
if noptional > 0 {
if defl == "" {
panic ( fmt . Sprintf ( "assertion type %q primary key header %q has no default, optional primary keys must be a proper suffix of the primary key" , at . Name , k ) )
}
2022-04-05 10:04:48 +02:00
}
if defl != "" {
2022-02-17 18:29:50 +01:00
noptional ++
}
}
if len ( at . OptionalPrimaryKeyDefaults ) != noptional {
panic ( fmt . Sprintf ( "assertion type %q has defaults values for unknown primary key headers" , at . Name ) )
}
}
2016-10-14 14:53:38 +02:00
// MaxSupportedFormat returns the maximum supported format iteration for the type.
func ( at * AssertionType ) MaxSupportedFormat ( ) int {
return maxSupportedFormat [ at . Name ]
}
2024-03-13 15:22:05 +00:00
// SequenceForming returns true if the assertion type has a positive
2020-07-01 17:22:40 +02:00
// integer >= 1 as the last component (preferably called "sequence")
2020-06-11 18:10:55 +02:00
// of its primary key over which the assertions of the type form
2020-06-29 13:51:54 +02:00
// sequences, usually without gaps, one sequence per sequence key (the
// primary key prefix omitting the sequence number).
// See SequenceMember.
2020-06-11 18:10:55 +02:00
func ( at * AssertionType ) SequenceForming ( ) bool {
return at . flags & sequenceForming != 0
}
2022-02-26 20:57:25 +01:00
// AcceptablePrimaryKey returns whether the given key could be an acceptable primary key for this type, allowing for the omission of optional primary key headers.
func ( at * AssertionType ) AcceptablePrimaryKey ( key [ ] string ) bool {
n := len ( at . PrimaryKey )
nopt := len ( at . OptionalPrimaryKeyDefaults )
ninp := len ( key )
if ninp > n || ninp < ( n - nopt ) {
return false
}
return true
}
2016-01-20 20:44:45 +01:00
// Understood assertion types.
2016-01-20 20:22:00 +01:00
var (
2023-12-08 15:42:15 +01:00
AccountType = & AssertionType { "account" , [ ] string { "account-id" } , nil , assembleAccount , 0 }
AccountKeyType = & AssertionType { "account-key" , [ ] string { "public-key-sha3-384" } , nil , assembleAccountKey , 0 }
RepairType = & AssertionType { "repair" , [ ] string { "brand-id" , "repair-id" } , nil , assembleRepair , sequenceForming }
ModelType = & AssertionType { "model" , [ ] string { "series" , "brand-id" , "model" } , nil , assembleModel , 0 }
SerialType = & AssertionType { "serial" , [ ] string { "brand-id" , "model" , "serial" } , nil , assembleSerial , 0 }
BaseDeclarationType = & AssertionType { "base-declaration" , [ ] string { "series" } , nil , assembleBaseDeclaration , 0 }
SnapDeclarationType = & AssertionType { "snap-declaration" , [ ] string { "series" , "snap-id" } , nil , assembleSnapDeclaration , 0 }
SnapBuildType = & AssertionType { "snap-build" , [ ] string { "snap-sha3-384" } , nil , assembleSnapBuild , 0 }
SnapRevisionType = & AssertionType { "snap-revision" , [ ] string { "snap-sha3-384" , "provenance" } , map [ string ] string { "provenance" : naming . DefaultProvenance } , assembleSnapRevision , 0 }
SnapDeveloperType = & AssertionType { "snap-developer" , [ ] string { "snap-id" , "publisher-id" } , nil , assembleSnapDeveloper , 0 }
SystemUserType = & AssertionType { "system-user" , [ ] string { "brand-id" , "email" } , nil , assembleSystemUser , 0 }
ValidationType = & AssertionType { "validation" , [ ] string { "series" , "snap-id" , "approved-snap-id" , "approved-snap-revision" } , nil , assembleValidation , 0 }
ValidationSetType = & AssertionType { "validation-set" , [ ] string { "series" , "account-id" , "name" , "sequence" } , nil , assembleValidationSet , sequenceForming }
StoreType = & AssertionType { "store" , [ ] string { "store" } , nil , assembleStore , 0 }
PreseedType = & AssertionType { "preseed" , [ ] string { "series" , "brand-id" , "model" , "system-label" } , nil , assemblePreseed , 0 }
SnapResourceRevisionType = & AssertionType { "snap-resource-revision" , [ ] string { "snap-id" , "resource-name" , "resource-sha3-384" , "provenance" } , map [ string ] string { "provenance" : naming . DefaultProvenance } , assembleSnapResourceRevision , 0 }
2023-12-12 19:36:08 +01:00
SnapResourcePairType = & AssertionType { "snap-resource-pair" , [ ] string { "snap-id" , "resource-name" , "resource-revision" , "snap-revision" , "provenance" } , map [ string ] string { "provenance" : naming . DefaultProvenance } , assembleSnapResourcePair , 0 }
2024-06-05 10:53:12 +01:00
RegistryType = & AssertionType { "registry" , [ ] string { "account-id" , "name" } , nil , assembleRegistry , jsonBody }
2015-11-17 17:12:08 +01:00
2023-12-12 19:36:08 +01:00
// ...
2015-11-10 18:33:36 +01:00
)
2016-08-12 11:28:39 +02:00
// Assertion types without a definite authority set (on the wire and/or self-signed).
2016-07-29 18:14:18 +02:00
var (
2022-02-17 18:29:50 +01:00
DeviceSessionRequestType = & AssertionType { "device-session-request" , [ ] string { "brand-id" , "model" , "serial" } , nil , assembleDeviceSessionRequest , noAuthority }
SerialRequestType = & AssertionType { "serial-request" , nil , nil , assembleSerialRequest , noAuthority }
AccountKeyRequestType = & AssertionType { "account-key-request" , [ ] string { "public-key-sha3-384" } , nil , assembleAccountKeyRequest , noAuthority }
2016-07-29 18:14:18 +02:00
)
2016-01-20 21:22:39 +01:00
var typeRegistry = map [ string ] * AssertionType {
2023-12-08 15:42:15 +01:00
AccountType . Name : AccountType ,
AccountKeyType . Name : AccountKeyType ,
ModelType . Name : ModelType ,
SerialType . Name : SerialType ,
BaseDeclarationType . Name : BaseDeclarationType ,
SnapDeclarationType . Name : SnapDeclarationType ,
SnapBuildType . Name : SnapBuildType ,
SnapRevisionType . Name : SnapRevisionType ,
SnapDeveloperType . Name : SnapDeveloperType ,
SystemUserType . Name : SystemUserType ,
ValidationType . Name : ValidationType ,
ValidationSetType . Name : ValidationSetType ,
RepairType . Name : RepairType ,
StoreType . Name : StoreType ,
PreseedType . Name : PreseedType ,
SnapResourceRevisionType . Name : SnapResourceRevisionType ,
2023-12-12 19:36:08 +01:00
SnapResourcePairType . Name : SnapResourcePairType ,
2024-06-05 10:53:12 +01:00
RegistryType . Name : RegistryType ,
2016-08-12 11:28:39 +02:00
// no authority
2016-08-30 19:42:01 +02:00
DeviceSessionRequestType . Name : DeviceSessionRequestType ,
SerialRequestType . Name : SerialRequestType ,
AccountKeyRequestType . Name : AccountKeyRequestType ,
2016-01-20 21:22:39 +01:00
}
2016-01-20 21:18:47 +01:00
2017-01-20 16:55:42 +01:00
// Type returns the AssertionType with name or nil
func Type ( name string ) * AssertionType {
return typeRegistry [ name ]
}
2017-06-30 10:13:04 +01:00
// TypeNames returns a sorted list of known assertion type names.
func TypeNames ( ) [ ] string {
names := make ( [ ] string , 0 , len ( typeRegistry ) )
for k := range typeRegistry {
names = append ( names , k )
}
sort . Strings ( names )
return names
}
2016-10-14 14:53:38 +02:00
var maxSupportedFormat = map [ string ] int { }
func init ( ) {
// register maxSupportedFormats while breaking initialisation loop
2017-01-24 17:16:58 +01:00
// 1: plugs and slots
// 2: support for $SLOT()/$PLUG()/$MISSING
2018-09-14 13:53:46 +02:00
// 3: support for on-store/on-brand/on-model device scope constraints
2019-11-27 17:29:30 +01:00
// 4: support for plug-names/slot-names constraints
2021-05-28 09:44:22 +02:00
// 5: alt attr matcher usage (was unused before, has new behavior now)
2024-06-10 16:45:47 +01:00
// 6: support for $PLUG_PUBLISHER_ID/$SLOT_PUBLISHER_ID in attr constraints
maxSupportedFormat [ SnapDeclarationType . Name ] = 6
2020-05-06 12:16:02 +02:00
// 1: support to limit to device serials
2022-10-19 10:38:34 +02:00
// 2: support for user-presence constraint
maxSupportedFormat [ SystemUserType . Name ] = 2
2022-01-26 16:45:03 +01:00
2023-08-08 15:43:19 +02:00
// 1: support for constraints
maxSupportedFormat [ AccountKeyType . Name ] = 1
2022-02-17 18:29:50 +01:00
for _ , at := range typeRegistry {
at . validate ( )
}
2016-10-14 14:53:38 +02:00
}
2016-10-14 21:25:53 +02:00
func MockMaxSupportedFormat ( assertType * AssertionType , maxFormat int ) ( restore func ( ) ) {
prev := maxSupportedFormat [ assertType . Name ]
maxSupportedFormat [ assertType . Name ] = maxFormat
return func ( ) {
maxSupportedFormat [ assertType . Name ] = prev
}
}
2022-02-26 18:58:47 +01:00
func MockOptionalPrimaryKey ( assertType * AssertionType , key , defaultValue string ) ( restore func ( ) ) {
osutil . MustBeTestBinary ( "mocking new assertion optional primary keys can be done only from tests" )
oldPrimaryKey := assertType . PrimaryKey
oldOptionalPrimaryKeyDefaults := assertType . OptionalPrimaryKeyDefaults
newOptionalPrimaryKeyDefaults := make ( map [ string ] string , len ( oldOptionalPrimaryKeyDefaults ) + 1 )
for k , defl := range oldOptionalPrimaryKeyDefaults {
newOptionalPrimaryKeyDefaults [ k ] = defl
}
assertType . PrimaryKey = append ( assertType . PrimaryKey , key )
assertType . OptionalPrimaryKeyDefaults = newOptionalPrimaryKeyDefaults
newOptionalPrimaryKeyDefaults [ key ] = defaultValue
return func ( ) {
assertType . PrimaryKey = oldPrimaryKey
assertType . OptionalPrimaryKeyDefaults = oldOptionalPrimaryKeyDefaults
}
}
2017-01-20 16:55:42 +01:00
var formatAnalyzer = map [ * AssertionType ] func ( headers map [ string ] interface { } , body [ ] byte ) ( formatnum int , err error ) {
2023-08-08 15:43:19 +02:00
AccountKeyType : accountKeyFormatAnalyze ,
2017-01-20 16:55:42 +01:00
SnapDeclarationType : snapDeclarationFormatAnalyze ,
2020-06-15 12:12:12 +02:00
SystemUserType : systemUserFormatAnalyze ,
2017-01-20 16:55:42 +01:00
}
2020-04-19 17:18:45 +02:00
// MaxSupportedFormats returns a mapping between assertion type names
// and corresponding max supported format if it is >= min. Typical
// usage passes 1 or 0 for min.
func MaxSupportedFormats ( min int ) ( maxFormats map [ string ] int ) {
if min == 0 {
maxFormats = make ( map [ string ] int , len ( typeRegistry ) )
} else {
maxFormats = make ( map [ string ] int )
}
for name := range typeRegistry {
m := maxSupportedFormat [ name ]
if m >= min {
maxFormats [ name ] = m
}
}
return maxFormats
}
2017-01-20 16:55:42 +01:00
// SuggestFormat returns a minimum format that supports the features that would be used by an assertion with the given components.
func SuggestFormat ( assertType * AssertionType , headers map [ string ] interface { } , body [ ] byte ) ( formatnum int , err error ) {
analyzer := formatAnalyzer [ assertType ]
if analyzer == nil {
// no analyzer, format 0 is all there is
return 0 , nil
}
2017-02-01 20:56:02 +01:00
formatnum , err = analyzer ( headers , body )
if err != nil {
return 0 , fmt . Errorf ( "assertion %s: %v" , assertType . Name , err )
}
return formatnum , nil
2016-01-20 20:22:00 +01:00
}
2017-09-12 16:34:53 +02:00
// HeadersFromPrimaryKey constructs a headers mapping from the
// primaryKey values and the assertion type, it errors if primaryKey
2022-02-26 15:48:51 +01:00
// does not cover all the non-optional primary key headers or provides
// too many values.
2017-09-12 16:34:53 +02:00
func HeadersFromPrimaryKey ( assertType * AssertionType , primaryKey [ ] string ) ( headers map [ string ] string , err error ) {
2022-04-21 17:11:33 +02:00
if ! assertType . AcceptablePrimaryKey ( primaryKey ) {
2017-09-12 16:34:53 +02:00
return nil , fmt . Errorf ( "primary key has wrong length for %q assertion" , assertType . Name )
}
2022-04-21 17:11:33 +02:00
ninp := len ( primaryKey )
2017-09-12 16:34:53 +02:00
headers = make ( map [ string ] string , len ( assertType . PrimaryKey ) )
for i , name := range assertType . PrimaryKey {
2022-02-26 15:48:51 +01:00
var keyVal string
if i < ninp {
keyVal = primaryKey [ i ]
if keyVal == "" {
return nil , fmt . Errorf ( "primary key %q header cannot be empty" , name )
}
} else {
keyVal = assertType . OptionalPrimaryKeyDefaults [ name ]
2017-09-12 22:30:17 +02:00
}
headers [ name ] = keyVal
2017-09-12 16:34:53 +02:00
}
return headers , nil
}
2021-02-03 16:28:04 +00:00
// HeadersFromSequenceKey constructs a headers mapping from the
// sequenceKey values and the sequence forming assertion type,
// it errors if sequenceKey has the wrong length; the length must be
// one less than the primary key of the given assertion type.
func HeadersFromSequenceKey ( assertType * AssertionType , sequenceKey [ ] string ) ( headers map [ string ] string , err error ) {
if ! assertType . SequenceForming ( ) {
return nil , fmt . Errorf ( "internal error: HeadersFromSequenceKey should only be used for sequence forming assertion types, got: %s" , assertType . Name )
}
if len ( sequenceKey ) != len ( assertType . PrimaryKey ) - 1 {
return nil , fmt . Errorf ( "sequence key has wrong length for %q assertion" , assertType . Name )
}
headers = make ( map [ string ] string , len ( sequenceKey ) )
for i , val := range sequenceKey {
key := assertType . PrimaryKey [ i ]
if val == "" {
return nil , fmt . Errorf ( "sequence key %q header cannot be empty" , key )
}
headers [ key ] = val
}
return headers , nil
}
2017-09-12 16:34:53 +02:00
// PrimaryKeyFromHeaders extracts the tuple of values from headers
// corresponding to a primary key under the assertion type, it errors
2022-02-26 15:26:40 +01:00
// if there are missing primary key headers unless they are optional
// in which case it fills in their default values.
2017-09-12 16:34:53 +02:00
func PrimaryKeyFromHeaders ( assertType * AssertionType , headers map [ string ] string ) ( primaryKey [ ] string , err error ) {
2022-02-26 15:26:40 +01:00
return keysFromHeaders ( assertType . PrimaryKey , headers , assertType . OptionalPrimaryKeyDefaults )
2020-06-23 12:51:42 +02:00
}
2022-02-26 15:26:40 +01:00
func keysFromHeaders ( keys [ ] string , headers map [ string ] string , defaults map [ string ] string ) ( keyValues [ ] string , err error ) {
2020-06-23 12:51:42 +02:00
keyValues = make ( [ ] string , len ( keys ) )
for i , k := range keys {
2017-09-12 16:34:53 +02:00
keyVal := headers [ k ]
if keyVal == "" {
2022-04-21 17:11:33 +02:00
keyVal = defaults [ k ]
if keyVal == "" {
2022-02-26 15:26:40 +01:00
return nil , fmt . Errorf ( "must provide primary key: %v" , k )
}
2017-09-12 16:34:53 +02:00
}
2020-06-23 12:51:42 +02:00
keyValues [ i ] = keyVal
2017-09-12 16:34:53 +02:00
}
2020-06-23 12:51:42 +02:00
return keyValues , nil
2017-09-12 16:34:53 +02:00
}
2022-02-26 17:08:11 +01:00
// ReducePrimaryKey produces a primary key prefix by omitting any
// suffix of optional primary key headers default values.
// Too short or long primary keys are returned as is.
func ReducePrimaryKey ( assertType * AssertionType , primaryKey [ ] string ) [ ] string {
n := len ( assertType . PrimaryKey )
nopt := len ( assertType . OptionalPrimaryKeyDefaults )
ninp := len ( primaryKey )
if ninp > n || ninp < ( n - nopt ) {
return primaryKey
}
reduced := make ( [ ] string , n - nopt , n )
copy ( reduced , primaryKey [ : n - nopt ] )
rest := ninp - ( n - nopt )
for i := ninp - 1 ; i >= n - nopt ; i -- {
defl := assertType . OptionalPrimaryKeyDefaults [ assertType . PrimaryKey [ i ] ]
if primaryKey [ i ] != defl {
break
}
// it matches the default value, leave it out
rest --
}
reduced = append ( reduced , primaryKey [ n - nopt : n - nopt + rest ] ... )
return reduced
}
2016-07-15 12:17:49 +02:00
// Ref expresses a reference to an assertion.
type Ref struct {
Type * AssertionType
PrimaryKey [ ] string
}
2016-08-26 08:32:09 +02:00
func ( ref * Ref ) String ( ) string {
2016-09-19 10:33:03 +02:00
pkStr := "-"
2016-09-16 23:30:28 +02:00
n := len ( ref . Type . PrimaryKey )
2022-02-26 17:08:11 +01:00
nopt := len ( ref . Type . OptionalPrimaryKeyDefaults )
ninp := len ( ref . PrimaryKey )
if ninp > n || ninp < ( n - nopt ) {
2016-09-16 23:30:28 +02:00
pkStr = "???"
} else if n > 0 {
2022-02-26 17:08:11 +01:00
pkStr = ref . PrimaryKey [ n - nopt - 1 ]
2016-09-16 23:30:28 +02:00
if n > 1 {
sfx := [ ] string { pkStr + ";" }
2022-02-26 17:08:11 +01:00
for i , k := range ref . Type . PrimaryKey [ : n - nopt - 1 ] {
2016-09-16 23:30:28 +02:00
sfx = append ( sfx , fmt . Sprintf ( "%s:%s" , k , ref . PrimaryKey [ i ] ) )
}
2022-02-26 17:08:11 +01:00
// optional primary keys
for i := n - nopt ; i < ninp ; i ++ {
v := ref . PrimaryKey [ i ]
k := ref . Type . PrimaryKey [ i ]
defl := ref . Type . OptionalPrimaryKeyDefaults [ k ]
if v != defl {
sfx = append ( sfx , fmt . Sprintf ( "%s:%s" , k , v ) )
}
}
2016-09-16 23:30:28 +02:00
pkStr = strings . Join ( sfx , " " )
}
}
return fmt . Sprintf ( "%s (%s)" , ref . Type . Name , pkStr )
2016-08-26 08:32:09 +02:00
}
2016-08-16 13:03:03 +02:00
// Unique returns a unique string representing the reference that can be used as a key in maps.
func ( ref * Ref ) Unique ( ) string {
2022-02-26 17:08:11 +01:00
return fmt . Sprintf ( "%s/%s" , ref . Type . Name , strings . Join ( ReducePrimaryKey ( ref . Type , ref . PrimaryKey ) , "/" ) )
2016-08-16 13:03:03 +02:00
}
// Resolve resolves the reference using the given find function.
func ( ref * Ref ) Resolve ( find func ( assertType * AssertionType , headers map [ string ] string ) ( Assertion , error ) ) ( Assertion , error ) {
2017-09-12 16:34:53 +02:00
headers , err := HeadersFromPrimaryKey ( ref . Type , ref . PrimaryKey )
if err != nil {
2016-08-16 13:03:03 +02:00
return nil , fmt . Errorf ( "%q assertion reference primary key has the wrong length (expected %v): %v" , ref . Type . Name , ref . Type . PrimaryKey , ref . PrimaryKey )
}
return find ( ref . Type , headers )
}
2020-04-05 16:20:52 +02:00
const RevisionNotKnown = - 1
2021-02-03 15:52:22 +00:00
// AtRevision represents an assertion at a given revision, possibly
// not known (RevisionNotKnown).
type AtRevision struct {
Ref
Revision int
}
func ( at * AtRevision ) String ( ) string {
s := at . Ref . String ( )
if at . Revision == RevisionNotKnown {
return s
}
return fmt . Sprintf ( "%s at revision %d" , s , at . Revision )
}
// AtSequence references a sequence forming assertion at a given sequence point,
// possibly <=0 (meaning not specified) and revision, possibly not known
// (RevisionNotKnown).
// Setting Pinned = true means pinning at the given sequence point (which must be
// set, i.e. > 0). Pinned sequence forming assertion will be updated to the
2021-02-04 11:36:38 +00:00
// latest revision at the specified sequence point.
2021-02-03 11:16:11 +00:00
type AtSequence struct {
Type * AssertionType
SequenceKey [ ] string
Sequence int
Pinned bool
Revision int
}
// Unique returns a unique string representing the sequence by its sequence key
// that can be used as a key in maps.
func ( at * AtSequence ) Unique ( ) string {
return fmt . Sprintf ( "%s/%s" , at . Type . Name , strings . Join ( at . SequenceKey , "/" ) )
}
func ( at * AtSequence ) String ( ) string {
2021-02-03 15:52:22 +00:00
var pkStr string
if len ( at . SequenceKey ) != len ( at . Type . PrimaryKey ) - 1 {
2021-02-03 11:16:11 +00:00
pkStr = "???"
2021-02-03 15:52:22 +00:00
} else {
n := 0
// omit series if present in the primary key
if at . Type . PrimaryKey [ 0 ] == "series" {
n ++
2021-02-03 11:16:11 +00:00
}
2021-02-03 15:52:22 +00:00
pkStr = strings . Join ( at . SequenceKey [ n : ] , "/" )
2021-02-03 11:16:11 +00:00
if at . Sequence > 0 {
2021-02-03 15:52:22 +00:00
sep := "/"
if at . Pinned {
sep = "="
}
pkStr = fmt . Sprintf ( "%s%s%d" , pkStr , sep , at . Sequence )
2021-02-03 11:16:11 +00:00
}
}
2021-02-03 15:52:22 +00:00
sk := fmt . Sprintf ( "%s %s" , at . Type . Name , pkStr )
2021-02-03 11:16:11 +00:00
if at . Revision == RevisionNotKnown {
return sk
}
return fmt . Sprintf ( "%s at revision %d" , sk , at . Revision )
}
// Resolve resolves the sequence with known sequence number using the given find function.
func ( at * AtSequence ) Resolve ( find func ( assertType * AssertionType , headers map [ string ] string ) ( Assertion , error ) ) ( Assertion , error ) {
2021-02-03 16:28:04 +00:00
if at . Sequence <= 0 {
hdrs , err := HeadersFromSequenceKey ( at . Type , at . SequenceKey )
if err != nil {
return nil , fmt . Errorf ( "%q assertion reference sequence key %v is invalid: %v" , at . Type . Name , at . SequenceKey , err )
}
return nil , & NotFoundError {
Type : at . Type ,
Headers : hdrs ,
}
}
2021-02-03 11:16:11 +00:00
pkey := append ( at . SequenceKey , fmt . Sprintf ( "%d" , at . Sequence ) )
headers , err := HeadersFromPrimaryKey ( at . Type , pkey )
if err != nil {
return nil , fmt . Errorf ( "%q assertion reference primary key has the wrong length (expected %v): %v" , at . Type . Name , at . Type . PrimaryKey , pkey )
}
return find ( at . Type , headers )
}
2015-11-10 18:33:36 +01:00
// Assertion represents an assertion through its general elements.
type Assertion interface {
2015-11-17 10:34:52 +01:00
// Type returns the type of this assertion
2016-01-20 20:22:00 +01:00
Type ( ) * AssertionType
2016-10-14 14:53:38 +02:00
// Format returns the format iteration of this assertion
Format ( ) int
2016-10-17 19:57:08 +02:00
// SupportedFormat returns whether the assertion uses a supported
2016-10-14 14:53:38 +02:00
// format iteration. If false the assertion might have been only
// partially parsed.
SupportedFormat ( ) bool
2015-11-17 10:34:52 +01:00
// Revision returns the revision of this assertion
2015-11-10 18:33:36 +01:00
Revision ( ) int
2022-08-24 14:00:14 +02:00
// AuthorityID returns the authority responsible for this
// assertion
2015-11-10 18:33:36 +01:00
AuthorityID ( ) string
// Header retrieves the header with name
2016-07-27 15:21:36 +02:00
Header ( name string ) interface { }
2015-11-10 18:33:36 +01:00
2016-01-08 09:23:51 +01:00
// Headers returns the complete headers
2016-07-27 15:21:36 +02:00
Headers ( ) map [ string ] interface { }
// HeaderString retrieves the string value of header with name or ""
HeaderString ( name string ) string
2016-01-08 09:23:51 +01:00
2015-11-17 10:34:52 +01:00
// Body returns the body of this assertion
2015-11-10 18:33:36 +01:00
Body ( ) [ ] byte
2015-11-16 14:44:21 +01:00
// Signature returns the signed content and its unprocessed signature
2015-11-16 14:46:25 +01:00
Signature ( ) ( content , signature [ ] byte )
2016-07-15 12:17:49 +02:00
2016-08-12 18:19:27 +02:00
// SignKeyID returns the key id for the key that signed this assertion.
SignKeyID ( ) string
2016-07-15 12:17:49 +02:00
// Prerequisites returns references to the prerequisite assertions for the validity of this one.
Prerequisites ( ) [ ] * Ref
2016-08-19 10:39:22 +02:00
// Ref returns a reference representing this assertion.
Ref ( ) * Ref
2020-04-19 19:15:59 +02:00
// At returns an AtRevision referencing this assertion at its revision.
At ( ) * AtRevision
2015-11-10 18:33:36 +01:00
}
2020-06-11 18:10:55 +02:00
// SequenceMember is implemented by assertions of sequence forming types.
type SequenceMember interface {
Assertion
2020-06-29 13:51:54 +02:00
// Sequence returns the sequence number of this assertion.
2020-06-11 18:10:55 +02:00
Sequence ( ) int
}
2016-09-02 18:54:24 +01:00
// customSigner represents an assertion with special arrangements for its signing key (e.g. self-signed), rather than the usual case where an assertion is signed by its authority.
type customSigner interface {
2016-09-01 16:39:39 +01:00
// signKey returns the public key material for the key that signed this assertion. See also SignKeyID.
signKey ( ) PublicKey
}
2016-07-11 14:53:56 +01:00
// MediaType is the media type for encoded assertions on the wire.
2016-01-26 19:24:13 +01:00
const MediaType = "application/x.ubuntu.assertion"
2015-11-30 16:23:39 +01:00
// assertionBase is the concrete base to hold representation data for actual assertions.
type assertionBase struct {
2016-07-27 15:21:36 +02:00
headers map [ string ] interface { }
2015-11-10 18:33:36 +01:00
body [ ] byte
2016-10-14 14:53:38 +02:00
// parsed format iteration
format int
2015-11-10 18:33:36 +01:00
// parsed revision
revision int
// preserved content
content [ ] byte
2015-11-16 14:44:21 +01:00
// unprocessed signature
signature [ ] byte
2015-11-10 18:33:36 +01:00
}
2016-07-27 15:21:36 +02:00
// HeaderString retrieves the string value of header with name or ""
func ( ab * assertionBase ) HeaderString ( name string ) string {
s , _ := ab . headers [ name ] . ( string )
return s
}
2015-11-10 18:33:36 +01:00
// Type returns the assertion type.
2016-01-20 20:22:00 +01:00
func ( ab * assertionBase ) Type ( ) * AssertionType {
2016-07-27 15:21:36 +02:00
return Type ( ab . HeaderString ( "type" ) )
2015-11-10 18:33:36 +01:00
}
2016-10-14 14:53:38 +02:00
// Format returns the assertion format iteration.
func ( ab * assertionBase ) Format ( ) int {
return ab . format
}
2016-10-17 19:57:08 +02:00
// SupportedFormat returns whether the assertion uses a supported
2016-10-14 14:53:38 +02:00
// format iteration. If false the assertion might have been only
// partially parsed.
func ( ab * assertionBase ) SupportedFormat ( ) bool {
return ab . format <= maxSupportedFormat [ ab . HeaderString ( "type" ) ]
}
2015-11-10 18:33:36 +01:00
// Revision returns the assertion revision.
2015-11-30 16:23:39 +01:00
func ( ab * assertionBase ) Revision ( ) int {
2015-11-10 18:33:36 +01:00
return ab . revision
}
2022-08-24 14:00:14 +02:00
// AuthorityID returns the authority-id a.k.a the authority responsible for the assertion.
2015-11-30 16:23:39 +01:00
func ( ab * assertionBase ) AuthorityID ( ) string {
2016-07-27 15:21:36 +02:00
return ab . HeaderString ( "authority-id" )
2015-11-10 18:33:36 +01:00
}
// Header returns the value of an header by name.
2016-07-27 15:21:36 +02:00
func ( ab * assertionBase ) Header ( name string ) interface { } {
v := ab . headers [ name ]
if v == nil {
return nil
}
return copyHeader ( v )
2015-11-10 18:33:36 +01:00
}
2016-01-08 09:23:51 +01:00
// Headers returns the complete headers.
2016-07-27 15:21:36 +02:00
func ( ab * assertionBase ) Headers ( ) map [ string ] interface { } {
return copyHeaders ( ab . headers )
2016-01-08 09:23:51 +01:00
}
2015-11-10 18:33:36 +01:00
// Body returns the body of the assertion.
2015-11-30 16:23:39 +01:00
func ( ab * assertionBase ) Body ( ) [ ] byte {
2015-11-10 18:33:36 +01:00
return ab . body
}
2015-11-16 14:44:21 +01:00
// Signature returns the signed content and its unprocessed signature.
2015-11-30 16:23:39 +01:00
func ( ab * assertionBase ) Signature ( ) ( content , signature [ ] byte ) {
2015-11-16 14:44:21 +01:00
return ab . content , ab . signature
2015-11-10 18:33:36 +01:00
}
2016-08-12 18:19:27 +02:00
// SignKeyID returns the key id for the key that signed this assertion.
func ( ab * assertionBase ) SignKeyID ( ) string {
2016-08-01 23:10:40 +02:00
return ab . HeaderString ( "sign-key-sha3-384" )
2016-07-15 12:17:49 +02:00
}
// Prerequisites returns references to the prerequisite assertions for the validity of this one.
func ( ab * assertionBase ) Prerequisites ( ) [ ] * Ref {
return nil
}
2016-08-19 10:39:22 +02:00
// Ref returns a reference representing this assertion.
func ( ab * assertionBase ) Ref ( ) * Ref {
assertType := ab . Type ( )
primKey := make ( [ ] string , len ( assertType . PrimaryKey ) )
for i , name := range assertType . PrimaryKey {
primKey [ i ] = ab . HeaderString ( name )
}
return & Ref {
Type : assertType ,
PrimaryKey : primKey ,
}
}
2020-04-19 19:15:59 +02:00
// At returns an AtRevision referencing this assertion at its revision.
func ( ab * assertionBase ) At ( ) * AtRevision {
return & AtRevision { Ref : * ab . Ref ( ) , Revision : ab . Revision ( ) }
}
2022-03-14 17:35:33 +01:00
// expected interface is implemented
2015-11-30 16:23:39 +01:00
var _ Assertion = ( * assertionBase ) ( nil )
2015-11-10 18:33:36 +01:00
// Decode parses a serialized assertion.
2015-11-11 11:36:26 +01:00
//
// The expected serialisation format looks like:
//
2023-01-09 14:39:58 +00:00
// HEADER ("\n\n" BODY?)? "\n\n" SIGNATURE
2015-11-11 11:36:26 +01:00
//
// where:
//
2023-01-09 14:39:58 +00:00
// HEADER is a set of header entries separated by "\n"
// BODY can be arbitrary text,
// SIGNATURE is the signature
2015-11-11 11:36:26 +01:00
//
2017-02-17 13:24:07 +01:00
// Both BODY and HEADER must be UTF8.
//
2016-06-21 18:13:01 +02:00
// A header entry for a single line value (no '\n' in it) looks like:
2015-11-11 11:36:26 +01:00
//
2023-01-09 14:39:58 +00:00
// NAME ": " SIMPLEVALUE
2015-11-11 11:36:26 +01:00
//
2016-07-27 15:21:36 +02:00
// The format supports multiline text values (with '\n's in them) and
2017-02-17 15:16:11 +01:00
// lists or maps, possibly nested, with string scalars in them.
2016-02-11 11:13:07 +01:00
//
2016-07-27 15:21:36 +02:00
// For those a header entry looks like:
//
2023-01-09 14:39:58 +00:00
// NAME ":\n" MULTI(baseindent)
2016-07-27 15:21:36 +02:00
//
// where MULTI can be
//
// * (baseindent + 4)-space indented value (multiline text)
2017-02-17 13:24:07 +01:00
//
2016-07-27 15:21:36 +02:00
// * entries of a list each of the form:
//
2023-01-09 14:39:58 +00:00
// " "*baseindent " -" ( " " SIMPLEVALUE | "\n" MULTI )
2017-02-17 13:24:07 +01:00
//
// * entries of map each of the form:
//
2023-01-09 14:39:58 +00:00
// " "*baseindent " " NAME ":" ( " " SIMPLEVALUE | "\n" MULTI )
2016-07-27 15:21:36 +02:00
//
// baseindent starts at 0 and then grows with nesting matching the
2017-02-17 13:28:23 +01:00
// previous level introduction (e.g. the " "*baseindent " -" bit)
2016-07-27 15:21:36 +02:00
// length minus 1.
2016-02-11 11:13:07 +01:00
//
2016-07-29 18:14:18 +02:00
// In general the following headers are mandatory:
2015-11-11 11:36:26 +01:00
//
2023-01-09 14:39:58 +00:00
// type
// authority-id (except for on the wire/self-signed assertions like serial-request)
2015-11-16 14:23:58 +01:00
//
2016-06-21 18:13:01 +02:00
// Further for a given assertion type all the primary key headers
// must be non empty and must not contain '/'.
//
2016-07-27 15:21:36 +02:00
// The following headers expect string representing integer values and
// if omitted otherwise are assumed to be 0:
2015-11-16 15:45:52 +01:00
//
2023-01-09 14:39:58 +00:00
// revision (a positive int)
// body-length (expected to be equal to the length of BODY)
// format (a positive int for the format iteration of the type used)
2015-11-11 11:36:26 +01:00
//
2016-06-21 18:13:01 +02:00
// Times are expected to be in the RFC3339 format: "2006-01-02T15:04:05Z07:00".
2015-11-10 18:33:36 +01:00
func Decode ( serializedAssertion [ ] byte ) ( Assertion , error ) {
2015-11-16 14:32:50 +01:00
// copy to get an independent backstorage that can't be mutated later
assertionSnapshot := make ( [ ] byte , len ( serializedAssertion ) )
copy ( assertionSnapshot , serializedAssertion )
contentSignatureSplit := bytes . LastIndex ( assertionSnapshot , nlnl )
2015-11-10 18:33:36 +01:00
if contentSignatureSplit == - 1 {
return nil , fmt . Errorf ( "assertion content/signature separator not found" )
}
2015-11-16 14:32:50 +01:00
content := assertionSnapshot [ : contentSignatureSplit ]
signature := assertionSnapshot [ contentSignatureSplit + 2 : ]
2015-11-10 18:33:36 +01:00
headersBodySplit := bytes . Index ( content , nlnl )
var body , head [ ] byte
if headersBodySplit == - 1 {
head = content
} else {
body = content [ headersBodySplit + 2 : ]
2015-11-11 18:11:54 +01:00
if len ( body ) == 0 {
body = nil
}
2015-11-10 18:33:36 +01:00
head = content [ : headersBodySplit ]
}
2016-07-27 15:21:36 +02:00
headers , err := parseHeaders ( head )
2015-11-10 18:33:36 +01:00
if err != nil {
return nil , fmt . Errorf ( "parsing assertion headers: %v" , err )
}
2016-07-27 15:21:36 +02:00
return assemble ( headers , body , content , signature )
2016-01-22 18:47:51 +01:00
}
2016-01-28 11:01:46 +01:00
// Maximum assertion component sizes.
const (
MaxBodySize = 2 * 1024 * 1024
2016-01-29 11:25:59 +01:00
MaxHeadersSize = 128 * 1024
2016-01-28 11:01:46 +01:00
MaxSignatureSize = 128 * 1024
)
2016-02-02 16:51:36 +01:00
// Decoder parses a stream of assertions bundled by separating them with double newlines.
2016-01-22 18:47:51 +01:00
type Decoder struct {
2016-01-27 21:21:11 +01:00
rd io . Reader
initialBufSize int
b * bufio . Reader
err error
2016-01-29 11:25:59 +01:00
maxHeadersSize int
2016-01-28 11:01:46 +01:00
maxSigSize int
2017-06-21 16:47:23 +02:00
defaultMaxBodySize int
typeMaxBodySize map [ * AssertionType ] int
2016-01-22 18:47:51 +01:00
}
2016-01-29 14:27:31 +01:00
// initBuffer finishes a Decoder initialization by setting up the bufio.Reader,
// it returns the *Decoder for convenience of notation.
func ( d * Decoder ) initBuffer ( ) * Decoder {
d . b = bufio . NewReaderSize ( d . rd , d . initialBufSize )
return d
2016-01-22 18:47:51 +01:00
}
2017-06-21 16:47:23 +02:00
const defaultDecoderBufSize = 4096
2016-01-28 11:01:46 +01:00
2016-01-22 18:47:51 +01:00
// NewDecoder returns a Decoder to parse the stream of assertions from the reader.
func NewDecoder ( r io . Reader ) * Decoder {
2016-01-29 14:27:31 +01:00
return ( & Decoder {
2017-06-21 16:47:23 +02:00
rd : r ,
initialBufSize : defaultDecoderBufSize ,
maxHeadersSize : MaxHeadersSize ,
maxSigSize : MaxSignatureSize ,
defaultMaxBodySize : MaxBodySize ,
} ) . initBuffer ( )
}
// NewDecoderWithTypeMaxBodySize returns a Decoder to parse the stream of assertions from the reader enforcing optional per type max body sizes or the default one as fallback.
func NewDecoderWithTypeMaxBodySize ( r io . Reader , typeMaxBodySize map [ * AssertionType ] int ) * Decoder {
return ( & Decoder {
rd : r ,
initialBufSize : defaultDecoderBufSize ,
maxHeadersSize : MaxHeadersSize ,
maxSigSize : MaxSignatureSize ,
defaultMaxBodySize : MaxBodySize ,
typeMaxBodySize : typeMaxBodySize ,
2016-01-29 14:27:31 +01:00
} ) . initBuffer ( )
2016-01-22 18:47:51 +01:00
}
2016-01-27 21:21:11 +01:00
func ( d * Decoder ) peek ( size int ) ( [ ] byte , error ) {
buf , err := d . b . Peek ( size )
if err == bufio . ErrBufferFull {
rebuf , reerr := d . b . Peek ( d . b . Buffered ( ) )
if reerr != nil {
panic ( reerr )
}
mr := io . MultiReader ( bytes . NewBuffer ( rebuf ) , d . rd )
d . b = bufio . NewReaderSize ( mr , ( size / d . initialBufSize + 1 ) * d . initialBufSize )
buf , err = d . b . Peek ( size )
}
if err != nil && d . err == nil {
d . err = err
}
return buf , d . err
}
2016-01-29 13:04:47 +01:00
// NB: readExact and readUntil use peek underneath and their returned
// buffers are valid only until the next reading call
2016-01-27 21:21:11 +01:00
func ( d * Decoder ) readExact ( size int ) ( [ ] byte , error ) {
buf , err := d . peek ( size )
d . b . Discard ( len ( buf ) )
if len ( buf ) == size {
return buf , nil
}
if err == io . EOF {
return buf , io . ErrUnexpectedEOF
}
return buf , err
}
2016-01-28 11:01:46 +01:00
func ( d * Decoder ) readUntil ( delim [ ] byte , maxSize int ) ( [ ] byte , error ) {
2016-01-27 21:21:11 +01:00
last := 0
2016-01-28 11:01:46 +01:00
size := d . initialBufSize
2016-01-22 18:47:51 +01:00
for {
2016-01-27 21:21:11 +01:00
buf , err := d . peek ( size )
if i := bytes . Index ( buf [ last : ] , delim ) ; i >= 0 {
d . b . Discard ( last + i + len ( delim ) )
return buf [ : last + i + len ( delim ) ] , nil
2016-01-22 18:47:51 +01:00
}
2016-01-28 11:01:46 +01:00
// report errors only once we have consumed what is buffered
2016-01-27 21:21:11 +01:00
if err != nil && len ( buf ) == d . b . Buffered ( ) {
d . b . Discard ( len ( buf ) )
return buf , err
2016-01-22 18:47:51 +01:00
}
2016-01-27 21:21:11 +01:00
last = size - len ( delim ) + 1
2016-01-28 11:01:46 +01:00
size *= 2
if size > maxSize {
2016-01-29 11:53:28 +01:00
return nil , fmt . Errorf ( "maximum size exceeded while looking for delimiter %q" , delim )
2016-01-22 18:47:51 +01:00
}
}
}
// Decode parses the next assertion from the stream.
2016-01-25 13:50:00 +01:00
// It returns the error io.EOF at the end of a well-formed stream.
2016-01-27 21:21:11 +01:00
func ( d * Decoder ) Decode ( ) ( Assertion , error ) {
2016-01-22 18:47:51 +01:00
// read the headers and the nlnl separator after them
2016-01-29 11:25:59 +01:00
headAndSep , err := d . readUntil ( nlnl , d . maxHeadersSize )
2016-01-22 18:47:51 +01:00
if err != nil {
2016-01-28 11:01:46 +01:00
if err == io . EOF {
if len ( headAndSep ) != 0 {
return nil , io . ErrUnexpectedEOF
}
return nil , io . EOF
2016-01-22 18:47:51 +01:00
}
2016-01-29 11:25:59 +01:00
return nil , fmt . Errorf ( "error reading assertion headers: %v" , err )
2015-11-11 20:55:13 +01:00
}
2016-01-29 13:04:47 +01:00
headLen := len ( headAndSep ) - len ( nlnl )
2016-07-27 15:21:36 +02:00
headers , err := parseHeaders ( headAndSep [ : headLen ] )
2016-01-22 18:47:51 +01:00
if err != nil {
return nil , fmt . Errorf ( "parsing assertion headers: %v" , err )
}
2017-06-21 16:47:23 +02:00
typeStr , _ := headers [ "type" ] . ( string )
typ := Type ( typeStr )
2016-07-15 14:05:36 +02:00
length , err := checkIntWithDefault ( headers , "body-length" , 0 )
2016-01-22 18:47:51 +01:00
if err != nil {
return nil , fmt . Errorf ( "assertion: %v" , err )
}
2017-06-21 16:47:23 +02:00
if typMaxBodySize := d . typeMaxBodySize [ typ ] ; typMaxBodySize != 0 && length > typMaxBodySize {
return nil , fmt . Errorf ( "assertion body length %d exceeds maximum body size %d for %q assertions" , length , typMaxBodySize , typ . Name )
} else if length > d . defaultMaxBodySize {
2016-01-28 11:01:46 +01:00
return nil , fmt . Errorf ( "assertion body length %d exceeds maximum body size" , length )
}
2016-01-22 18:47:51 +01:00
2016-01-29 13:04:47 +01:00
// save the headers before we try to read more, and setup to capture
// the whole content in a buffer
contentBuf := bytes . NewBuffer ( make ( [ ] byte , 0 , len ( headAndSep ) + length ) )
contentBuf . Write ( headAndSep )
2016-01-22 18:47:51 +01:00
if length > 0 {
// read the body if length != 0
2016-01-29 13:04:47 +01:00
body , err := d . readExact ( length )
2016-01-22 18:47:51 +01:00
if err != nil {
return nil , err
}
2016-01-28 11:01:46 +01:00
contentBuf . Write ( body )
2016-01-22 18:47:51 +01:00
}
// try to read the end of body a.k.a content/signature separator
2016-01-28 11:01:46 +01:00
endOfBody , err := d . readUntil ( nlnl , d . maxSigSize )
2016-01-22 18:47:51 +01:00
if err != nil && err != io . EOF {
2016-01-28 11:01:46 +01:00
return nil , fmt . Errorf ( "error reading assertion trailer: %v" , err )
2016-01-22 18:47:51 +01:00
}
2016-01-29 13:04:47 +01:00
var sig [ ] byte
2016-01-22 18:47:51 +01:00
if bytes . Equal ( endOfBody , nlnl ) {
// we got the nlnl content/signature separator, read the signature now and the assertion/assertion nlnl separation
2016-01-28 11:01:46 +01:00
sig , err = d . readUntil ( nlnl , d . maxSigSize )
2016-01-22 18:47:51 +01:00
if err != nil && err != io . EOF {
2016-01-28 11:01:46 +01:00
return nil , fmt . Errorf ( "error reading assertion signature: %v" , err )
2016-01-22 18:47:51 +01:00
}
} else {
// we got the signature directly which is a ok format only if body length == 0
if length > 0 {
return nil , fmt . Errorf ( "missing content/signature separator" )
}
sig = endOfBody
2016-01-29 13:04:47 +01:00
contentBuf . Truncate ( headLen )
2016-01-22 18:47:51 +01:00
}
// normalize sig ending newlines
if bytes . HasSuffix ( sig , nlnl ) {
sig = sig [ : len ( sig ) - 1 ]
}
2016-01-29 13:04:47 +01:00
finalContent := contentBuf . Bytes ( )
var finalBody [ ] byte
if length > 0 {
finalBody = finalContent [ headLen + len ( nlnl ) : ]
}
2016-01-28 11:01:46 +01:00
finalSig := make ( [ ] byte , len ( sig ) )
copy ( finalSig , sig )
2016-07-27 15:21:36 +02:00
return assemble ( headers , finalBody , finalContent , finalSig )
2015-11-10 18:33:36 +01:00
}
2016-10-14 14:53:38 +02:00
func checkIteration ( headers map [ string ] interface { } , name string ) ( int , error ) {
iternum , err := checkIntWithDefault ( headers , name , 0 )
2015-11-18 18:08:59 +01:00
if err != nil {
return - 1 , err
}
2016-10-14 14:53:38 +02:00
if iternum < 0 {
return - 1 , fmt . Errorf ( "%s should be positive: %v" , name , iternum )
2015-11-18 18:08:59 +01:00
}
2016-10-14 14:53:38 +02:00
return iternum , nil
}
func checkFormat ( headers map [ string ] interface { } ) ( int , error ) {
return checkIteration ( headers , "format" )
}
func checkRevision ( headers map [ string ] interface { } ) ( int , error ) {
return checkIteration ( headers , "revision" )
2015-11-18 18:08:59 +01:00
}
2016-01-07 22:49:49 +01:00
// Assemble assembles an assertion from its components.
2016-07-27 15:21:36 +02:00
func Assemble ( headers map [ string ] interface { } , body , content , signature [ ] byte ) ( Assertion , error ) {
err := checkHeaders ( headers )
if err != nil {
return nil , err
}
return assemble ( headers , body , content , signature )
}
2022-08-24 14:00:14 +02:00
func checkAuthority ( _ * AssertionType , headers map [ string ] interface { } ) error {
2022-02-04 16:40:06 +01:00
if _ , err := checkNotEmptyString ( headers , "authority-id" ) ; err != nil {
2022-08-24 14:00:14 +02:00
return err
2022-02-04 16:40:06 +01:00
}
2022-08-24 14:00:14 +02:00
return nil
2022-02-04 16:40:06 +01:00
}
func checkNoAuthority ( assertType * AssertionType , headers map [ string ] interface { } ) error {
2022-02-14 11:44:12 +01:00
if _ , ok := headers [ "authority-id" ] ; ok {
2022-02-04 16:40:06 +01:00
return fmt . Errorf ( "%q assertion cannot have authority-id set" , assertType . Name )
}
return nil
}
2024-03-13 15:22:05 +00:00
func checkJSON ( assertType * AssertionType , body [ ] byte ) ( err error ) {
defer func ( ) {
if err != nil {
err = fmt . Errorf ( "assertion %s: %v" , assertType . Name , err )
}
} ( )
if body == nil {
return fmt . Errorf ( ` body must contain JSON ` )
}
var val interface { }
if err := json . Unmarshal ( body , & val ) ; err != nil {
return fmt . Errorf ( "invalid JSON in body: %v" , err )
}
formatted , err := json . MarshalIndent ( val , "" , " " )
if err != nil {
return fmt . Errorf ( "invalid JSON in body: %v" , err )
}
if ! reflect . DeepEqual ( body , formatted ) {
return fmt . Errorf ( ` JSON in body must be indented with 2 spaces and sort object entries by key ` )
}
return nil
}
2016-07-27 15:21:36 +02:00
// assemble is the internal variant of Assemble, assumes headers are already checked for supported types
func assemble ( headers map [ string ] interface { } , body , content , signature [ ] byte ) ( Assertion , error ) {
2016-07-15 14:05:36 +02:00
length , err := checkIntWithDefault ( headers , "body-length" , 0 )
2015-11-10 18:33:36 +01:00
if err != nil {
2015-11-26 17:35:01 +01:00
return nil , fmt . Errorf ( "assertion: %v" , err )
2015-11-10 18:33:36 +01:00
}
2015-11-11 18:15:14 +01:00
if length != len ( body ) {
return nil , fmt . Errorf ( "assertion body length and declared body-length don't match: %v != %v" , len ( body ) , length )
2015-11-10 18:33:36 +01:00
}
2016-08-25 11:36:59 +02:00
if ! utf8 . Valid ( body ) {
2022-02-08 19:44:36 +01:00
return nil , fmt . Errorf ( "assertion body is not utf8" )
2016-08-25 11:36:59 +02:00
}
2016-08-01 23:10:40 +02:00
if _ , err := checkDigest ( headers , "sign-key-sha3-384" , crypto . SHA3_384 ) ; err != nil {
return nil , fmt . Errorf ( "assertion: %v" , err )
}
2016-07-27 15:21:36 +02:00
typ , err := checkNotEmptyString ( headers , "type" )
2015-11-10 18:33:36 +01:00
if err != nil {
2015-11-26 17:12:46 +01:00
return nil , fmt . Errorf ( "assertion: %v" , err )
2015-11-10 18:33:36 +01:00
}
2016-01-20 20:22:00 +01:00
assertType := Type ( typ )
if assertType == nil {
2016-01-21 10:19:47 +01:00
return nil , fmt . Errorf ( "unknown assertion type: %q" , typ )
2016-01-20 20:22:00 +01:00
}
2015-11-10 18:33:36 +01:00
2024-03-13 15:22:05 +00:00
if assertType . flags & jsonBody != 0 {
if err := checkJSON ( assertType , body ) ; err != nil {
return nil , err
}
}
2016-08-12 11:28:39 +02:00
if assertType . flags & noAuthority == 0 {
2022-08-24 14:00:14 +02:00
if err := checkAuthority ( assertType , headers ) ; err != nil {
2016-07-29 18:14:18 +02:00
return nil , fmt . Errorf ( "assertion: %v" , err )
}
} else {
2022-02-04 16:40:06 +01:00
if err := checkNoAuthority ( assertType , headers ) ; err != nil {
return nil , err
2016-07-29 18:14:18 +02:00
}
}
2016-10-14 14:53:38 +02:00
formatnum , err := checkFormat ( headers )
if err != nil {
return nil , fmt . Errorf ( "assertion: %v" , err )
}
2016-02-04 19:16:03 +01:00
for _ , primKey := range assertType . PrimaryKey {
2022-02-17 18:29:50 +01:00
if _ , ok := headers [ primKey ] ; ! ok {
if defl := assertType . OptionalPrimaryKeyDefaults [ primKey ] ; defl != "" {
headers [ primKey ] = defl
}
}
2016-06-14 10:36:22 +02:00
if _ , err := checkPrimaryKey ( headers , primKey ) ; err != nil {
2016-02-04 19:16:03 +01:00
return nil , fmt . Errorf ( "assertion %s: %v" , assertType . Name , err )
}
}
2015-11-18 18:08:59 +01:00
revision , err := checkRevision ( headers )
2015-11-10 18:33:36 +01:00
if err != nil {
2015-11-26 17:35:01 +01:00
return nil , fmt . Errorf ( "assertion: %v" , err )
2015-11-10 18:33:36 +01:00
}
2016-01-22 18:47:51 +01:00
if len ( signature ) == 0 {
return nil , fmt . Errorf ( "empty assertion signature" )
}
2016-01-20 20:54:07 +01:00
assert , err := assertType . assembler ( assertionBase {
2015-11-16 14:44:21 +01:00
headers : headers ,
body : body ,
2016-10-14 14:53:38 +02:00
format : formatnum ,
2015-11-16 14:44:21 +01:00
revision : revision ,
content : content ,
signature : signature ,
2015-11-17 18:02:17 +01:00
} )
if err != nil {
2016-01-20 20:22:00 +01:00
return nil , fmt . Errorf ( "assertion %s: %v" , assertType . Name , err )
2015-11-17 18:02:17 +01:00
}
return assert , nil
2015-11-10 18:33:36 +01:00
}
2016-07-27 15:21:36 +02:00
func writeHeader ( buf * bytes . Buffer , headers map [ string ] interface { } , name string ) {
appendEntry ( buf , fmt . Sprintf ( "%s:" , name ) , headers [ name ] , 0 )
2015-11-18 18:08:59 +01:00
}
2016-07-27 15:21:36 +02:00
func assembleAndSign ( assertType * AssertionType , headers map [ string ] interface { } , body [ ] byte , privKey PrivateKey ) ( Assertion , error ) {
2016-01-20 21:18:47 +01:00
err := checkAssertType ( assertType )
2016-01-20 20:23:53 +01:00
if err != nil {
return nil , err
}
2016-08-12 11:28:39 +02:00
withAuthority := assertType . flags & noAuthority == 0
2024-03-13 15:22:05 +00:00
withJSONBody := assertType . flags & jsonBody != 0
2016-07-29 18:14:18 +02:00
2016-07-27 15:21:36 +02:00
err = checkHeaders ( headers )
if err != nil {
return nil , err
2015-11-18 18:08:59 +01:00
}
2016-07-27 15:21:36 +02:00
2016-08-25 11:36:59 +02:00
// there's no hint at all that we will need non-textual bodies,
// make sure we actually enforce that
if ! utf8 . Valid ( body ) {
return nil , fmt . Errorf ( "assertion body is not utf8" )
}
2024-03-13 15:22:05 +00:00
if withJSONBody {
if err := checkJSON ( assertType , body ) ; err != nil {
return nil , err
}
}
2016-07-27 15:21:36 +02:00
finalHeaders := copyHeaders ( headers )
2015-11-18 18:08:59 +01:00
bodyLength := len ( body )
finalBody := make ( [ ] byte , bodyLength )
copy ( finalBody , body )
2016-01-20 20:22:00 +01:00
finalHeaders [ "type" ] = assertType . Name
2015-11-18 18:08:59 +01:00
finalHeaders [ "body-length" ] = strconv . Itoa ( bodyLength )
2016-08-11 16:49:56 +02:00
finalHeaders [ "sign-key-sha3-384" ] = privKey . PublicKey ( ) . ID ( )
2015-11-18 18:08:59 +01:00
2016-07-29 18:14:18 +02:00
if withAuthority {
2022-08-24 14:00:14 +02:00
if err = checkAuthority ( assertType , finalHeaders ) ; err != nil {
2016-07-29 18:14:18 +02:00
return nil , err
}
} else {
2022-02-04 16:40:06 +01:00
if err := checkNoAuthority ( assertType , finalHeaders ) ; err != nil {
return nil , err
2016-07-29 18:14:18 +02:00
}
2015-11-18 18:08:59 +01:00
}
2016-10-14 14:53:38 +02:00
formatnum , err := checkFormat ( finalHeaders )
if err != nil {
return nil , err
}
2016-10-14 21:44:41 +02:00
if formatnum > assertType . MaxSupportedFormat ( ) {
return nil , fmt . Errorf ( "cannot sign %q assertion with format %d higher than max supported format %d" , assertType . Name , formatnum , assertType . MaxSupportedFormat ( ) )
}
2017-01-20 19:28:40 +01:00
suggestedFormat , err := SuggestFormat ( assertType , finalHeaders , finalBody )
2017-01-20 16:55:42 +01:00
if err != nil {
return nil , err
}
2017-01-20 19:28:40 +01:00
if suggestedFormat > formatnum {
return nil , fmt . Errorf ( "cannot sign %q assertion with format set to %d lower than min format %d covering included features" , assertType . Name , formatnum , suggestedFormat )
2017-01-20 16:55:42 +01:00
}
2015-11-18 18:08:59 +01:00
revision , err := checkRevision ( finalHeaders )
if err != nil {
return nil , err
}
2015-11-20 16:21:59 +01:00
buf := bytes . NewBufferString ( "type: " )
2016-01-20 20:22:00 +01:00
buf . WriteString ( assertType . Name )
2015-11-20 16:21:59 +01:00
2016-10-14 14:53:38 +02:00
if formatnum > 0 {
writeHeader ( buf , finalHeaders , "format" )
} else {
delete ( finalHeaders , "format" )
}
2016-07-29 18:14:18 +02:00
if withAuthority {
writeHeader ( buf , finalHeaders , "authority-id" )
}
2015-11-18 18:08:59 +01:00
if revision > 0 {
writeHeader ( buf , finalHeaders , "revision" )
} else {
delete ( finalHeaders , "revision" )
}
2015-11-19 15:37:57 +01:00
written := map [ string ] bool {
2016-08-01 23:10:40 +02:00
"type" : true ,
2016-10-14 14:53:38 +02:00
"format" : true ,
2016-08-01 23:10:40 +02:00
"authority-id" : true ,
"revision" : true ,
"body-length" : true ,
"sign-key-sha3-384" : true ,
2015-11-18 18:08:59 +01:00
}
2016-01-20 20:54:07 +01:00
for _ , primKey := range assertType . PrimaryKey {
2022-02-23 18:17:42 +01:00
defl := assertType . OptionalPrimaryKeyDefaults [ primKey ]
_ , ok := finalHeaders [ primKey ]
if ! ok && defl != "" {
// optional but expected to be set in headers
// in the result assertion
finalHeaders [ primKey ] = defl
continue
}
value , err := checkPrimaryKey ( finalHeaders , primKey )
if err != nil {
2015-11-18 18:08:59 +01:00
return nil , err
}
2022-02-23 18:17:42 +01:00
if value != defl {
writeHeader ( buf , finalHeaders , primKey )
}
2015-11-19 15:37:57 +01:00
written [ primKey ] = true
2015-11-18 18:08:59 +01:00
}
// emit other headers in lexicographic order
otherKeys := make ( [ ] string , 0 , len ( finalHeaders ) )
for name := range finalHeaders {
2015-11-19 15:37:57 +01:00
if ! written [ name ] {
2015-11-18 18:08:59 +01:00
otherKeys = append ( otherKeys , name )
}
}
sort . Strings ( otherKeys )
for _ , k := range otherKeys {
writeHeader ( buf , finalHeaders , k )
}
// body-length and body
if bodyLength > 0 {
writeHeader ( buf , finalHeaders , "body-length" )
} else {
delete ( finalHeaders , "body-length" )
}
2016-08-01 23:10:40 +02:00
// signing key reference
writeHeader ( buf , finalHeaders , "sign-key-sha3-384" )
2015-11-18 18:08:59 +01:00
if bodyLength > 0 {
buf . Grow ( bodyLength + 2 )
2015-12-17 14:57:40 +01:00
buf . Write ( nlnl )
2015-11-18 18:08:59 +01:00
buf . Write ( finalBody )
} else {
finalBody = nil
}
content := buf . Bytes ( )
2015-11-19 14:30:38 +01:00
signature , err := signContent ( content , privKey )
if err != nil {
2016-05-30 10:45:37 +02:00
return nil , fmt . Errorf ( "cannot sign assertion: %v" , err )
2015-11-19 14:30:38 +01:00
}
2015-12-03 08:54:36 +01:00
// be 'cat' friendly, add a ignored newline to the signature which is the last part of the encoded assertion
signature = append ( signature , '\n' )
2015-11-19 14:30:38 +01:00
2016-01-20 20:54:07 +01:00
assert , err := assertType . assembler ( assertionBase {
2015-11-18 18:08:59 +01:00
headers : finalHeaders ,
body : finalBody ,
2016-10-14 14:53:38 +02:00
format : formatnum ,
2015-11-18 18:08:59 +01:00
revision : revision ,
content : content ,
2015-11-19 14:30:38 +01:00
signature : signature ,
2015-11-18 18:08:59 +01:00
} )
if err != nil {
2016-01-20 20:22:00 +01:00
return nil , fmt . Errorf ( "cannot assemble assertion %s: %v" , assertType . Name , err )
2015-11-18 18:08:59 +01:00
}
return assert , nil
}
2016-08-12 11:28:39 +02:00
// SignWithoutAuthority assembles an assertion without a set authority with the provided information and signs it with the given private key.
func SignWithoutAuthority ( assertType * AssertionType , headers map [ string ] interface { } , body [ ] byte , privKey PrivateKey ) ( Assertion , error ) {
if assertType . flags & noAuthority == 0 {
return nil , fmt . Errorf ( "cannot sign assertions needing a definite authority with SignWithoutAuthority" )
2016-07-29 18:14:18 +02:00
}
return assembleAndSign ( assertType , headers , body , privKey )
}
2015-11-17 11:02:28 +01:00
// Encode serializes an assertion.
func Encode ( assert Assertion ) [ ] byte {
content , signature := assert . Signature ( )
needed := len ( content ) + 2 + len ( signature )
buf := bytes . NewBuffer ( make ( [ ] byte , 0 , needed ) )
buf . Write ( content )
2015-12-17 14:57:40 +01:00
buf . Write ( nlnl )
2015-11-17 11:02:28 +01:00
buf . Write ( signature )
return buf . Bytes ( )
}
2016-01-26 13:43:15 +01:00
2016-02-02 16:47:13 +01:00
// Encoder emits a stream of assertions bundled by separating them with double newlines.
2016-01-26 13:43:15 +01:00
type Encoder struct {
2016-02-02 16:47:13 +01:00
wr io . Writer
nextSep [ ] byte
2016-01-26 13:43:15 +01:00
}
// NewEncoder returns a Encoder to emit a stream of assertions to a writer.
func NewEncoder ( w io . Writer ) * Encoder {
return & Encoder { wr : w }
}
2017-06-22 22:55:25 +02:00
func ( enc * Encoder ) writeSep ( last byte ) error {
if last != '\n' {
_ , err := enc . wr . Write ( nl )
if err != nil {
return err
}
}
enc . nextSep = nl
return nil
}
// WriteEncoded writes the encoded assertion into the stream with the required separator.
func ( enc * Encoder ) WriteEncoded ( encoded [ ] byte ) error {
2016-01-26 13:43:15 +01:00
sz := len ( encoded )
if sz == 0 {
return fmt . Errorf ( "internal error: encoded assertion cannot be empty" )
}
2016-02-02 16:47:13 +01:00
_ , err := enc . wr . Write ( enc . nextSep )
2016-01-26 13:43:15 +01:00
if err != nil {
return err
}
2016-02-02 16:47:13 +01:00
_ , err = enc . wr . Write ( encoded )
if err != nil {
return err
}
2017-06-22 22:55:25 +02:00
return enc . writeSep ( encoded [ sz - 1 ] )
}
2016-02-02 16:47:13 +01:00
2017-06-22 22:55:25 +02:00
// WriteContentSignature writes the content and signature of an assertion into the stream with all the required separators.
func ( enc * Encoder ) WriteContentSignature ( content , signature [ ] byte ) error {
if len ( content ) == 0 {
return fmt . Errorf ( "internal error: content cannot be empty" )
}
sz := len ( signature )
if sz == 0 {
return fmt . Errorf ( "internal error: signature cannot be empty" )
}
_ , err := enc . wr . Write ( enc . nextSep )
if err != nil {
return err
}
_ , err = enc . wr . Write ( content )
if err != nil {
return err
}
_ , err = enc . wr . Write ( nlnl )
if err != nil {
return err
}
_ , err = enc . wr . Write ( signature )
if err != nil {
return err
}
return enc . writeSep ( signature [ sz - 1 ] )
2016-01-26 13:43:15 +01:00
}
// Encode emits the assertion into the stream with the required separator.
2016-01-27 21:21:11 +01:00
// Errors here are always about writing given that Encode() itself cannot error.
2016-01-26 13:43:15 +01:00
func ( enc * Encoder ) Encode ( assert Assertion ) error {
2017-06-22 22:55:25 +02:00
return enc . WriteContentSignature ( assert . Signature ( ) )
2016-01-26 13:43:15 +01:00
}
2016-07-29 18:14:18 +02:00
2016-08-12 11:28:39 +02:00
// SignatureCheck checks the signature of the assertion against the given public key. Useful for assertions with no authority.
2016-07-29 18:14:18 +02:00
func SignatureCheck ( assert Assertion , pubKey PublicKey ) error {
content , encodedSig := assert . Signature ( )
sig , err := decodeSignature ( encodedSig )
if err != nil {
return err
}
err = pubKey . verify ( content , sig )
if err != nil {
return fmt . Errorf ( "failed signature verification: %v" , err )
}
return nil
}