github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/teams/loader_types.go (about)

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