forked from keybase/client
/
loader_types.go
195 lines (165 loc) · 5.5 KB
/
loader_types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package teams
import (
"crypto/sha256"
"fmt"
"github.com/keybase/client/go/libkb"
"github.com/keybase/client/go/protocol/keybase1"
)
// --------------------------------------------------
// An operation that occurs simultaneously on the child and parent team chains.
// This struct holds the child half of the operation.
type parentChildOperation struct {
// The seqno in the parent sigchain that corresponds to this operation.
parentSeqno keybase1.Seqno
// The type of the child link
linkType libkb.SigchainV2Type
// The new subteam name. The only PCOs at the mo' are subteam renames.
newName keybase1.TeamName
}
// --------------------------------------------------
type SignerX struct {
signer keybase1.UserVersion
// Whether the user is definitely an implicit admin
implicitAdmin bool
}
func NewSignerX(signer keybase1.UserVersion, implicitAdmin bool) SignerX {
return SignerX{signer, implicitAdmin}
}
// --------------------------------------------------
type ChainLinkUnpacked struct {
source *SCChainLink
outerLink *libkb.OuterLinkV2WithMetadata
// inner is nil if the link is stubbed
inner *SCChainLinkPayload
// nil if the link is stubbed
innerLinkID libkb.LinkID
// nil if the link is stubbed
innerTeamID keybase1.TeamID
}
func UnpackChainLink(link *SCChainLink) (*ChainLinkUnpacked, error) {
return unpackChainLink(link)
}
func unpackChainLink(link *SCChainLink) (*ChainLinkUnpacked, error) {
var outerLink *libkb.OuterLinkV2WithMetadata
var err error
switch {
case link.Sig != "":
outerLink, err = libkb.DecodeOuterLinkV2(link.Sig)
case link.SigV2Payload != "":
outerLink, err = libkb.DecodeStubbedOuterLinkV2(link.SigV2Payload)
default:
return nil, fmt.Errorf("cannot decode chain link, no sig v2 payload")
}
if err != nil {
return nil, fmt.Errorf("unpack outer: %v", err)
}
err = outerLink.AssertSomeFields(link.Version, link.Seqno)
if err != nil {
return nil, err
}
var inner *SCChainLinkPayload
var innerLinkID libkb.LinkID
var innerTeamID keybase1.TeamID
if link.Payload == "" {
// stubbed inner link
} else {
payload, err := link.UnmarshalPayload()
if err != nil {
return nil, fmt.Errorf("unmarshaling link payload: %v", err)
}
inner = &payload
tmp := sha256.Sum256([]byte(link.Payload))
innerLinkID = libkb.LinkID(tmp[:])
innerTeamID, err = inner.TeamID()
if err != nil {
return nil, err
}
}
ret := &ChainLinkUnpacked{
source: link,
outerLink: outerLink,
inner: inner,
innerLinkID: innerLinkID,
innerTeamID: innerTeamID,
}
return ret, nil
}
func (l *ChainLinkUnpacked) Seqno() keybase1.Seqno { return l.outerLink.Seqno }
func (l *ChainLinkUnpacked) SeqType() keybase1.SeqType { return l.outerLink.SeqType }
func (l *ChainLinkUnpacked) Prev() libkb.LinkID { return l.outerLink.Prev }
func (l *ChainLinkUnpacked) LinkID() libkb.LinkID { return l.outerLink.LinkID() }
func (l *ChainLinkUnpacked) SigID() keybase1.SigID { return l.outerLink.SigID() }
func (l *ChainLinkUnpacked) LinkType() libkb.SigchainV2Type { return l.outerLink.LinkType }
func (l *ChainLinkUnpacked) isStubbed() bool { return l.inner == nil }
func (l ChainLinkUnpacked) SignatureMetadata() keybase1.SignatureMetadata {
return l.inner.SignatureMetadata()
}
func (l ChainLinkUnpacked) SigChainLocation() keybase1.SigChainLocation {
return l.inner.SigChainLocation()
}
func (l ChainLinkUnpacked) LinkTriple() keybase1.LinkTriple {
return keybase1.LinkTriple{
Seqno: l.Seqno(),
SeqType: l.SeqType(),
LinkID: l.LinkID().Export(),
}
}
func (l ChainLinkUnpacked) TeamAdmin() *SCTeamAdmin { return l.inner.TeamAdmin() }
func (i *SCChainLinkPayload) SignatureMetadata() keybase1.SignatureMetadata {
return keybase1.SignatureMetadata{
PrevMerkleRootSigned: i.Body.MerkleRoot.ToMerkleRootV2(),
SigChainLocation: i.SigChainLocation(),
Time: keybase1.TimeFromSeconds(int64(i.Ctime)),
}
}
func (l *ChainLinkUnpacked) AssertInnerOuterMatch() (err error) {
if l.inner == nil {
return fmt.Errorf("cannot check inner-outer match without inner link")
}
var prev libkb.LinkID
if l.inner.Prev != nil {
prev, err = libkb.LinkIDFromHex(*l.inner.Prev)
if err != nil {
return err
}
}
linkType, err := libkb.SigchainV2TypeFromV1TypeTeams(l.inner.Body.Type)
if err != nil {
if l.outerLink.LinkType.IsSupportedTeamType() {
// Supported outer type but unrecognized inner type.
return err
}
if !l.outerLink.IgnoreIfUnsupported {
// Unsupported outer type marked as critical.
return NewUnsupportedLinkTypeError(l.outerLink.LinkType, l.inner.Body.Type)
}
// If the inner link type is not recognized, and the outer link type is not a valid
// team link type. Then this may be a link type from the future.
// Let it slide without really checking that the inner and outer types match
// (because this client doesn't know the mapping).
// By assigning this tautology, which will always pass AssertFields.
linkType = l.outerLink.LinkType
}
useSeqType := l.inner.SeqType
if l.outerLink.SeqType == 0 {
// There are links where seq_type is unset on the outer link
// but set on the inner link.
// Let these pass.
useSeqType = l.outerLink.SeqType
}
return l.outerLink.AssertFields(
l.inner.Body.Version,
l.inner.Seqno,
prev,
l.innerLinkID,
linkType,
useSeqType,
l.inner.IgnoreIfUnsupported,
nil)
}
func (l *ChainLinkUnpacked) PTKGeneration() (ret keybase1.PerTeamKeyGeneration) {
if l.isStubbed() || l.inner.Body.Team == nil || l.inner.Body.Team.PerTeamKey == nil {
return ret
}
return l.inner.Body.Team.PerTeamKey.Generation
}