github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/teams/teams.go (about) 1 package teams 2 3 import ( 4 "crypto/rand" 5 "crypto/sha256" 6 "encoding/base64" 7 "encoding/json" 8 "errors" 9 "fmt" 10 "sort" 11 "time" 12 13 "github.com/keybase/go-codec/codec" 14 15 "golang.org/x/crypto/nacl/secretbox" 16 "golang.org/x/net/context" 17 18 "github.com/keybase/client/go/libkb" 19 "github.com/keybase/client/go/protocol/gregor1" 20 "github.com/keybase/client/go/protocol/keybase1" 21 "github.com/keybase/client/go/sig3" 22 hidden "github.com/keybase/client/go/teams/hidden" 23 jsonw "github.com/keybase/go-jsonw" 24 ) 25 26 // Teamer is an interface that can fit a materialized Team (just below) or intermediary temporary products 27 // that are available during the team load process. It has access to both the main and hidden chain data 28 // so that we can ask questions like "what is the maximal on-chain PTK generation." 29 type Teamer interface { 30 MainChain() *keybase1.TeamData 31 HiddenChain() *keybase1.HiddenTeamChain 32 } 33 34 // A snapshot of a team's state. 35 // Not threadsafe. 36 type Team struct { 37 libkb.Contextified 38 39 ID keybase1.TeamID 40 Data *keybase1.TeamData 41 Hidden *keybase1.HiddenTeamChain 42 43 keyManager *TeamKeyManager 44 45 // rotated is set by rotateBoxes after rotating team key. 46 rotated bool 47 } 48 49 // Used to order multiple signatures to post 50 type teamSectionWithLinkType struct { 51 linkType libkb.LinkType 52 section SCTeamSection 53 } 54 55 func (t *Team) MainChain() *keybase1.TeamData { return t.Data } 56 func (t *Team) HiddenChain() *keybase1.HiddenTeamChain { return t.Hidden } 57 58 var _ Teamer = (*Team)(nil) 59 60 func NewTeam(ctx context.Context, g *libkb.GlobalContext, teamData *keybase1.TeamData, hidden *keybase1.HiddenTeamChain) *Team { 61 return &Team{ 62 Contextified: libkb.NewContextified(g), 63 64 ID: teamData.ID(), 65 Data: teamData, 66 Hidden: hidden, 67 } 68 } 69 70 func (t *Team) CanSkipKeyRotation() bool { 71 // Only applies for >=200 member teams. 72 const MinTeamSize = 200 73 // Aim for one rotation every 24h. 74 const KeyRotateInterval = time.Duration(24) * time.Hour 75 76 if t.IsImplicit() { 77 // Do not do this optimization for implicit teams. 78 return false 79 } 80 81 if t.IsOpen() { 82 // Skip all rotations in open teams. 83 return true 84 } 85 86 // If cannot decide because of an error, return default false. 87 members, err := t.UsersWithRoleOrAbove(keybase1.TeamRole_BOT) 88 if err != nil { 89 return false 90 } 91 if len(members) < MinTeamSize { 92 // Not a big team 93 return false 94 } 95 96 now := t.G().Clock().Now() 97 duration := now.Sub(time.Unix(int64(t.chain().GetLatestPerTeamKeyCTime()), 0)) 98 if duration > KeyRotateInterval { //nolint 99 // Last key rotation was more than predefined interval. 100 return false 101 } 102 // Team is big and key was rotated recently - can skip rotation. 103 return true 104 } 105 106 func (t *Team) calculateAndCacheMemberCount(ctx context.Context) (int, error) { 107 m := libkb.NewMetaContext(ctx, t.G()) 108 members, err := t.Members() 109 if err != nil { 110 m.Debug("| Failed to get Members() for team %q: %v", t.ID, err) 111 return 0, err 112 } 113 114 memberUIDs := make(map[keybase1.UID]bool) 115 for _, uv := range members.AllUserVersions() { 116 memberUIDs[uv.Uid] = true 117 } 118 119 inviteMDs := t.chain().ActiveInvites() 120 for _, inviteMD := range inviteMDs { 121 invite := inviteMD.Invite 122 invID := invite.Id 123 category, err := invite.Type.C() 124 if err != nil { 125 m.Debug("| Failed parsing invite %q in team %q: %v", invID, t.ID, err) 126 return 0, err 127 } 128 129 if category == keybase1.TeamInviteCategory_KEYBASE { 130 uv, err := invite.KeybaseUserVersion() 131 if err != nil { 132 m.Debug("| Failed parsing invite %q in team %q: %v", invID, t.ID, err) 133 return 0, err 134 } 135 136 memberUIDs[uv.Uid] = true 137 } 138 139 } 140 count := len(memberUIDs) - len(members.Bots) - len(members.RestrictedBots) 141 t.G().TeamMemberCountCache.Set(t.ID, count) 142 return count, nil 143 } 144 145 func (t *Team) chain() *TeamSigChainState { 146 return &TeamSigChainState{inner: t.Data.Chain, hidden: t.Hidden} 147 } 148 149 func (t *Team) Name() keybase1.TeamName { 150 return t.Data.Name 151 } 152 153 func (t *Team) Generation() keybase1.PerTeamKeyGeneration { 154 return t.chain().GetLatestGeneration() 155 } 156 157 func (t *Team) IsPublic() bool { 158 return t.chain().IsPublic() 159 } 160 161 func (t *Team) IsImplicit() bool { 162 return t.chain().IsImplicit() 163 } 164 165 func (t *Team) IsSubteam() bool { 166 return t.chain().IsSubteam() 167 } 168 169 func (t *Team) IsOpen() bool { 170 return t.chain().IsOpen() 171 } 172 173 func (t *Team) OpenTeamJoinAs() keybase1.TeamRole { 174 return t.chain().inner.OpenTeamJoinAs 175 } 176 177 func (t *Team) KBFSTLFIDs() []keybase1.TLFID { 178 return t.chain().inner.TlfIDs 179 } 180 181 func (t *Team) LatestKBFSTLFID() (res keybase1.TLFID) { 182 ids := t.KBFSTLFIDs() 183 if len(ids) > 0 { 184 res = ids[len(ids)-1] 185 } 186 return res 187 } 188 189 func (t *Team) KBFSCryptKeys(ctx context.Context, appType keybase1.TeamApplication) []keybase1.CryptKey { 190 return t.Data.TlfCryptKeys[appType] 191 } 192 193 func (t *Team) getKeyManager(ctx context.Context) (km *TeamKeyManager, err error) { 194 if t.keyManager == nil { 195 gen := t.chain().GetLatestGeneration() 196 item, err := GetAndVerifyPerTeamKey(t.MetaContext(ctx), t, gen) 197 if err != nil { 198 return nil, err 199 } 200 t.keyManager, err = NewTeamKeyManagerWithSeedItem(t.ID, item) 201 if err != nil { 202 return nil, err 203 } 204 } 205 return t.keyManager, nil 206 } 207 208 func (t *Team) SharedSecret(ctx context.Context) (ret keybase1.PerTeamKeySeed, err error) { 209 defer t.G().CTrace(ctx, "Team#SharedSecret", &err)() 210 km, err := t.getKeyManager(ctx) 211 if err != nil { 212 return ret, err 213 } 214 return km.SharedSecret(), nil 215 } 216 217 func (t *Team) KBFSKey(ctx context.Context) (keybase1.TeamApplicationKey, error) { 218 return t.ApplicationKey(ctx, keybase1.TeamApplication_KBFS) 219 } 220 221 func (t *Team) ChatKey(ctx context.Context) (keybase1.TeamApplicationKey, error) { 222 return t.ApplicationKey(ctx, keybase1.TeamApplication_CHAT) 223 } 224 225 func (t *Team) GitMetadataKey(ctx context.Context) (keybase1.TeamApplicationKey, error) { 226 return t.ApplicationKey(ctx, keybase1.TeamApplication_GIT_METADATA) 227 } 228 229 func (t *Team) SeitanInviteTokenKeyLatest(ctx context.Context) (keybase1.TeamApplicationKey, error) { 230 return t.ApplicationKey(ctx, keybase1.TeamApplication_SEITAN_INVITE_TOKEN) 231 } 232 233 func (t *Team) SaltpackEncryptionKeyLatest(ctx context.Context) (keybase1.TeamApplicationKey, error) { 234 return t.ApplicationKey(ctx, keybase1.TeamApplication_SALTPACK) 235 } 236 237 func (t *Team) ChatKeyAtGeneration(ctx context.Context, generation keybase1.PerTeamKeyGeneration) (keybase1.TeamApplicationKey, error) { 238 return t.ApplicationKeyAtGeneration(ctx, keybase1.TeamApplication_CHAT, generation) 239 } 240 241 func (t *Team) SaltpackEncryptionKeyAtGeneration(ctx context.Context, generation keybase1.PerTeamKeyGeneration) (keybase1.TeamApplicationKey, error) { 242 return t.ApplicationKeyAtGeneration(ctx, keybase1.TeamApplication_SALTPACK, generation) 243 } 244 245 func (t *Team) SeitanInviteTokenKeyAtGeneration(ctx context.Context, generation keybase1.PerTeamKeyGeneration) (keybase1.TeamApplicationKey, error) { 246 return t.ApplicationKeyAtGeneration(ctx, keybase1.TeamApplication_SEITAN_INVITE_TOKEN, generation) 247 } 248 249 func (t *Team) SigningKID(ctx context.Context) (kid keybase1.KID, err error) { 250 gen := t.chain().GetLatestGeneration() 251 chainKey, err := newTeamSigChainState(t).GetPerTeamKeyAtGeneration(gen) 252 if err != nil { 253 return kid, err 254 } 255 return chainKey.SigKID, nil 256 } 257 258 func (t *Team) SigningKey(ctx context.Context) (key libkb.NaclSigningKeyPair, err error) { 259 km, err := t.getKeyManager(ctx) 260 if err != nil { 261 return key, err 262 } 263 return km.SigningKey() 264 } 265 266 func (t *Team) EncryptionKey(ctx context.Context) (key libkb.NaclDHKeyPair, err error) { 267 km, err := t.getKeyManager(ctx) 268 if err != nil { 269 return key, err 270 } 271 return km.EncryptionKey() 272 } 273 274 func (t *Team) encryptionKeyAtGen(ctx context.Context, gen keybase1.PerTeamKeyGeneration) (key libkb.NaclDHKeyPair, err error) { 275 item, err := GetAndVerifyPerTeamKey(libkb.NewMetaContext(ctx, t.G()), t, gen) 276 if err != nil { 277 return key, err 278 } 279 keyManager, err := NewTeamKeyManagerWithSeedItem(t.ID, item) 280 if err != nil { 281 return key, err 282 } 283 return keyManager.EncryptionKey() 284 } 285 286 func (t *Team) IsMember(ctx context.Context, uv keybase1.UserVersion) bool { 287 role, err := t.MemberRole(ctx, uv) 288 if err != nil { 289 t.G().Log.CDebugf(ctx, "error getting user role: %s", err) 290 return false 291 } 292 return role != keybase1.TeamRole_NONE 293 } 294 295 func (t *Team) MemberCtime(ctx context.Context, uv keybase1.UserVersion) *keybase1.Time { 296 return t.chain().MemberCtime(uv) 297 } 298 299 func (t *Team) MemberRole(ctx context.Context, uv keybase1.UserVersion) (keybase1.TeamRole, error) { 300 return t.chain().GetUserRole(uv) 301 } 302 303 func (t *Team) WasMostRecentlyAddedByInvitelink(uv keybase1.UserVersion) bool { 304 chain := t.chain().inner 305 logPoints, ok := chain.UserLog[uv] 306 if !ok { 307 return false 308 } 309 latestLogPointAddedAtIdx := len(logPoints) - 1 310 for _, inviteMD := range chain.InviteMetadatas { 311 for _, usedInvite := range inviteMD.UsedInvites { 312 if usedInvite.Uv == uv { 313 invitelinkLogPointAddedAtIdx := usedInvite.LogPoint 314 if invitelinkLogPointAddedAtIdx == latestLogPointAddedAtIdx { 315 return true 316 } 317 // don't exit early otherwise, since there might be a newer invite 318 } 319 } 320 } 321 return false 322 } 323 324 func (t *Team) myRole(ctx context.Context) (keybase1.TeamRole, error) { 325 uv, err := t.currentUserUV(ctx) 326 if err != nil { 327 return keybase1.TeamRole_NONE, err 328 } 329 role, err := t.MemberRole(ctx, uv) 330 return role, err 331 } 332 333 func (t *Team) UserVersionByUID(ctx context.Context, uid keybase1.UID) (keybase1.UserVersion, error) { 334 return t.chain().GetLatestUVWithUID(uid) 335 } 336 337 func (t *Team) AllUserVersionsByUID(ctx context.Context, uid keybase1.UID) []keybase1.UserVersion { 338 return t.chain().GetAllUVsWithUID(uid) 339 } 340 341 func (t *Team) AllUserVersions(ctx context.Context) []keybase1.UserVersion { 342 return t.chain().GetAllUVs() 343 } 344 345 func (t *Team) UsersWithRole(role keybase1.TeamRole) ([]keybase1.UserVersion, error) { 346 return t.chain().GetUsersWithRole(role) 347 } 348 349 func (t *Team) UsersWithRoleOrAbove(role keybase1.TeamRole) ([]keybase1.UserVersion, error) { 350 return t.chain().GetUsersWithRoleOrAbove(role) 351 } 352 353 func (t *Team) UserLastJoinTime(u keybase1.UserVersion) (time keybase1.Time, err error) { 354 return t.chain().GetUserLastJoinTime(u) 355 } 356 357 // UserLastRoleChangeTime returns the time of the last role change for user 358 // in team. If the user left the team as a last change, the time of such leave 359 // event is returned. If the user was never in the team, then this function 360 // returns time=0 and wasMember=false. 361 func (t *Team) UserLastRoleChangeTime(u keybase1.UserVersion) (time keybase1.Time, wasMember bool) { 362 return t.chain().GetUserLastRoleChangeTime(u) 363 } 364 365 func (t *Team) Settings() keybase1.TeamSettings { 366 return keybase1.TeamSettings{ 367 Open: t.IsOpen(), 368 JoinAs: t.chain().inner.OpenTeamJoinAs, 369 } 370 } 371 372 func (t *Team) Members() (keybase1.TeamMembers, error) { 373 var members keybase1.TeamMembers 374 375 x, err := t.UsersWithRole(keybase1.TeamRole_OWNER) 376 if err != nil { 377 return keybase1.TeamMembers{}, err 378 } 379 members.Owners = x 380 381 x, err = t.UsersWithRole(keybase1.TeamRole_ADMIN) 382 if err != nil { 383 return keybase1.TeamMembers{}, err 384 } 385 members.Admins = x 386 387 x, err = t.UsersWithRole(keybase1.TeamRole_WRITER) 388 if err != nil { 389 return keybase1.TeamMembers{}, err 390 } 391 members.Writers = x 392 393 x, err = t.UsersWithRole(keybase1.TeamRole_READER) 394 if err != nil { 395 return keybase1.TeamMembers{}, err 396 } 397 members.Readers = x 398 399 x, err = t.UsersWithRole(keybase1.TeamRole_BOT) 400 if err != nil { 401 return keybase1.TeamMembers{}, err 402 } 403 members.Bots = x 404 405 x, err = t.UsersWithRole(keybase1.TeamRole_RESTRICTEDBOT) 406 if err != nil { 407 return keybase1.TeamMembers{}, err 408 } 409 members.RestrictedBots = x 410 411 return members, nil 412 } 413 414 func (t *Team) ImplicitTeamDisplayName(ctx context.Context) (res keybase1.ImplicitTeamDisplayName, err error) { 415 return t.implicitTeamDisplayName(ctx, false) 416 } 417 418 func (t *Team) ImplicitTeamDisplayNameNoConflicts(ctx context.Context) (res keybase1.ImplicitTeamDisplayName, err error) { 419 return t.implicitTeamDisplayName(ctx, true) 420 } 421 422 func (t *Team) implicitTeamDisplayName(ctx context.Context, skipConflicts bool) (res keybase1.ImplicitTeamDisplayName, err error) { 423 defer t.G().CTrace(ctx, "Team.ImplicitTeamDisplayName", &err)() 424 425 impName := keybase1.ImplicitTeamDisplayName{ 426 IsPublic: t.IsPublic(), 427 ConflictInfo: nil, // TODO should we know this here? 428 } 429 430 seenKBUsers := make(map[string]bool) 431 members, err := t.Members() 432 if err != nil { 433 return res, err 434 } 435 // Add the keybase owners 436 for _, member := range members.Owners { 437 name, err := t.G().GetUPAKLoader().LookupUsername(ctx, member.Uid) 438 if err != nil { 439 return res, err 440 } 441 impName.Writers.KeybaseUsers = append(impName.Writers.KeybaseUsers, name.String()) 442 } 443 // Add the keybase readers 444 for _, member := range members.Readers { 445 name, err := t.G().GetUPAKLoader().LookupUsername(ctx, member.Uid) 446 if err != nil { 447 return res, err 448 } 449 impName.Readers.KeybaseUsers = append(impName.Readers.KeybaseUsers, name.String()) 450 } 451 // Mark all the usernames we know about 452 for _, name := range append(impName.Writers.KeybaseUsers, impName.Readers.KeybaseUsers...) { 453 seenKBUsers[name] = true 454 } 455 456 // Add the invites 457 isFullyResolved := true 458 459 inviteMDs := t.chain().ActiveInvites() 460 for _, inviteMD := range inviteMDs { 461 invite := inviteMD.Invite 462 invtyp, err := invite.Type.C() 463 if err != nil { 464 t.G().Log.CDebugf(ctx, "ImplicitTeamDisplayName: failed to compute type of invite: %s", err.Error()) 465 continue 466 } 467 switch invtyp { 468 case keybase1.TeamInviteCategory_SBS: 469 sa := keybase1.SocialAssertion{ 470 User: string(invite.Name), 471 Service: keybase1.SocialAssertionService(string(invite.Type.Sbs())), 472 } 473 switch invite.Role { 474 case keybase1.TeamRole_OWNER: 475 impName.Writers.UnresolvedUsers = append(impName.Writers.UnresolvedUsers, sa) 476 case keybase1.TeamRole_READER: 477 impName.Readers.UnresolvedUsers = append(impName.Readers.UnresolvedUsers, sa) 478 default: 479 return res, fmt.Errorf("implicit team contains invite to role: %v (%v)", invite.Role, invite.Id) 480 } 481 isFullyResolved = false 482 case keybase1.TeamInviteCategory_KEYBASE: 483 // Check to make sure we don't already have the user in the name 484 uv, err := invite.KeybaseUserVersion() 485 if err != nil { 486 return res, err 487 } 488 normalizedUsername, err := t.G().GetUPAKLoader().LookupUsername(ctx, uv.Uid) 489 if err != nil { 490 return res, err 491 } 492 username := normalizedUsername.String() 493 494 if seenKBUsers[username] { 495 continue 496 } 497 seenKBUsers[username] = true 498 switch invite.Role { 499 case keybase1.TeamRole_OWNER: 500 impName.Writers.KeybaseUsers = append(impName.Writers.KeybaseUsers, username) 501 case keybase1.TeamRole_READER: 502 impName.Readers.KeybaseUsers = append(impName.Readers.KeybaseUsers, username) 503 default: 504 return res, fmt.Errorf("implicit team contains invite to role: %v (%v)", invite.Role, 505 invite.Id) 506 } 507 case keybase1.TeamInviteCategory_PHONE, keybase1.TeamInviteCategory_EMAIL: 508 typ, err := invite.Type.String() 509 if err != nil { 510 return res, fmt.Errorf("Failed to handle invite type %v: %s", invtyp, err) 511 } 512 sa := keybase1.SocialAssertion{ 513 User: string(invite.Name), 514 Service: keybase1.SocialAssertionService(typ), 515 } 516 switch invite.Role { 517 case keybase1.TeamRole_OWNER: 518 impName.Writers.UnresolvedUsers = append(impName.Writers.UnresolvedUsers, sa) 519 case keybase1.TeamRole_READER: 520 impName.Readers.UnresolvedUsers = append(impName.Readers.UnresolvedUsers, sa) 521 default: 522 return res, fmt.Errorf("implicit team contains invite to role: %v (%v)", invite.Role, invite.Id) 523 } 524 isFullyResolved = false 525 case keybase1.TeamInviteCategory_UNKNOWN: 526 return res, fmt.Errorf("unknown invite type in implicit team: %q", invite.Type.Unknown()) 527 default: 528 return res, fmt.Errorf("unrecognized invite type in implicit team: %v", invtyp) 529 } 530 } 531 if !skipConflicts { 532 impName, err = GetConflictInfo(ctx, t.G(), t.ID, isFullyResolved, impName) 533 if err != nil { 534 return res, err 535 } 536 } 537 return impName, nil 538 } 539 540 func (t *Team) ImplicitTeamDisplayNameString(ctx context.Context) (string, error) { 541 impName, err := t.ImplicitTeamDisplayName(ctx) 542 if err != nil { 543 return "", err 544 } 545 return FormatImplicitTeamDisplayName(ctx, t.G(), impName) 546 } 547 548 func (t *Team) NextSeqno() keybase1.Seqno { 549 return t.CurrentSeqno() + 1 550 } 551 552 func (t *Team) CurrentSeqno() keybase1.Seqno { 553 return t.chain().GetLatestSeqno() 554 } 555 556 func (t *Team) AllApplicationKeys(ctx context.Context, application keybase1.TeamApplication) (res []keybase1.TeamApplicationKey, err error) { 557 return AllApplicationKeys(t.MetaContext(ctx), t, application, t.chain().GetLatestGeneration()) 558 } 559 560 func (t *Team) AllApplicationKeysWithKBFS(ctx context.Context, application keybase1.TeamApplication) (res []keybase1.TeamApplicationKey, err error) { 561 return AllApplicationKeysWithKBFS(t.MetaContext(ctx), t, application, 562 t.chain().GetLatestGeneration()) 563 } 564 565 // ApplicationKey returns the most recent key for an application. 566 func (t *Team) ApplicationKey(ctx context.Context, application keybase1.TeamApplication) (keybase1.TeamApplicationKey, error) { 567 latestGen := t.chain().GetLatestGeneration() 568 return t.ApplicationKeyAtGeneration(ctx, application, latestGen) 569 } 570 571 func (t *Team) ApplicationKeyAtGeneration(ctx context.Context, 572 application keybase1.TeamApplication, generation keybase1.PerTeamKeyGeneration) (res keybase1.TeamApplicationKey, err error) { 573 return ApplicationKeyAtGeneration(t.MetaContext(ctx), t, application, generation) 574 } 575 576 func (t *Team) ApplicationKeyAtGenerationWithKBFS(ctx context.Context, 577 application keybase1.TeamApplication, generation keybase1.PerTeamKeyGeneration) (res keybase1.TeamApplicationKey, err error) { 578 return ApplicationKeyAtGenerationWithKBFS(t.MetaContext(ctx), t, application, generation) 579 } 580 581 func (t *Team) TeamBotSettings() (map[keybase1.UserVersion]keybase1.TeamBotSettings, error) { 582 botSettings := t.chain().TeamBotSettings() 583 // It's possible that we added a RESTRICTEDBOT member without posting any 584 // settings for them. Fill in default values (no access) for those members 585 restrictedBots, err := t.UsersWithRole(keybase1.TeamRole_RESTRICTEDBOT) 586 if err != nil { 587 return nil, err 588 } 589 for _, uv := range restrictedBots { 590 if _, ok := botSettings[uv]; !ok { 591 botSettings[uv] = keybase1.TeamBotSettings{} 592 } 593 } 594 return botSettings, nil 595 } 596 597 func addSummaryHash(section *SCTeamSection, boxes *PerTeamSharedSecretBoxes) error { 598 if boxes == nil { 599 return nil 600 } 601 bps := boxes.boxPublicSummary 602 if bps == nil || bps.IsEmpty() { 603 return nil 604 } 605 bsh := SCTeamBoxSummaryHash(bps.HashHexEncoded()) 606 section.BoxSummaryHash = &bsh 607 return nil 608 } 609 610 func (t *Team) Rotate(ctx context.Context, rt keybase1.RotationType) (err error) { 611 return t.rotate(ctx, rt) 612 } 613 614 func (t *Team) rotate(ctx context.Context, rt keybase1.RotationType) (err error) { 615 mctx := t.MetaContext(ctx).WithLogTag("ROT") 616 defer mctx.Trace(fmt.Sprintf("Team#rotate(%s,%s)", t.ID, rt), &err)() 617 618 rt, err = hidden.CheckFeatureGateForSupportWithRotationType(mctx, t.ID, rt) 619 if err != nil { 620 return err 621 } 622 623 // initialize key manager 624 if _, err := t.SharedSecret(mctx.Ctx()); err != nil { 625 return err 626 } 627 628 mr, err := t.G().MerkleClient.FetchRootFromServer(mctx, libkb.TeamMerkleFreshnessForAdmin) 629 if err != nil { 630 return err 631 } 632 633 // load an empty member set (no membership changes) 634 memSet := newMemberSet() 635 636 // Try to get the admin perms if they are available, if not, proceed anyway 637 var admin *SCTeamAdmin 638 admin, err = t.getAdminPermission(mctx.Ctx()) 639 if err != nil { 640 mctx.Debug("Rotate: unable to get admin permission: %v, attempting without admin section", err) 641 admin = nil 642 } 643 644 if err := t.ForceMerkleRootUpdate(mctx.Ctx()); err != nil { 645 return err 646 } 647 648 section := SCTeamSection{ 649 ID: SCTeamID(t.ID), 650 Admin: admin, 651 Implicit: t.IsImplicit(), 652 Public: t.IsPublic(), 653 } 654 655 // create the team section of the signature 656 section.Members, err = memSet.Section() 657 if err != nil { 658 return err 659 } 660 661 // rotate the team key for all current members 662 secretBoxes, perTeamKeySection, teamEKPayload, err := t.rotateBoxes(mctx.Ctx(), memSet) 663 if err != nil { 664 return err 665 } 666 section.PerTeamKey = perTeamKeySection 667 668 err = addSummaryHash(§ion, secretBoxes) 669 if err != nil { 670 return err 671 } 672 673 // post the change to the server 674 payloadArgs := sigPayloadArgs{ 675 secretBoxes: secretBoxes, 676 teamEKPayload: teamEKPayload, 677 } 678 679 if rt == keybase1.RotationType_VISIBLE { 680 err = t.rotatePostVisible(mctx.Ctx(), section, mr, payloadArgs) 681 } else { 682 err = t.rotatePostHidden(mctx.Ctx(), section, mr, payloadArgs) 683 } 684 if err != nil { 685 return err 686 } 687 688 t.storeTeamEKPayload(mctx.Ctx(), teamEKPayload) 689 createTeambotKeys(t.G(), t.ID, memSet.restrictedBotRecipientUids()) 690 691 return nil 692 } 693 694 func (t *Team) rotatePostVisible(ctx context.Context, section SCTeamSection, mr *libkb.MerkleRoot, payloadArgs sigPayloadArgs) error { 695 ratchet, err := t.makeRatchet(ctx) 696 if err != nil { 697 return err 698 } 699 section.Ratchets = ratchet.ToTeamSection() 700 payloadArgs.ratchetBlindingKeys = ratchet.ToSigPayload() 701 702 latestSeqno, err := t.postChangeItem(ctx, section, libkb.LinkTypeRotateKey, mr, payloadArgs) 703 if err != nil { 704 return err 705 } 706 return t.notify(ctx, keybase1.TeamChangeSet{KeyRotated: true}, latestSeqno) 707 } 708 709 func (t *Team) rotatePostHidden(ctx context.Context, section SCTeamSection, mr *libkb.MerkleRoot, payloadArgs sigPayloadArgs) error { 710 mctx := libkb.NewMetaContext(ctx, t.G()) 711 712 // Generate a "sig multi item" that we POST up to the API endpoint 713 smi, ratchet, err := t.rotateHiddenGenerateSigMultiItem(mctx, section, mr) 714 if err != nil { 715 return err 716 } 717 718 links := []libkb.SigMultiItem{*smi} 719 720 err = t.precheckLinksToPost(ctx, links) 721 if err != nil { 722 return err 723 } 724 725 // Combine the "sig multi item" above with the various off-chain items, like boxes. 726 payload := t.sigPayload(links, payloadArgs) 727 728 // Post the changes up to the server 729 err = t.postMulti(mctx, payload) 730 if err != nil { 731 return err 732 } 733 734 // Inform local caching that we've ratcheted forward the hidden chain with a change 735 // that we made. 736 tmp := mctx.G().GetHiddenTeamChainManager().Ratchet(mctx, t.ID, *ratchet) 737 if tmp != nil { 738 mctx.Warning("Failed to ratchet forward team chain: %s", tmp.Error()) 739 } 740 741 // We rotated the key but didn't change the visibile chain. 742 // TODO: We should be able to send a local notification here with 743 // new hidden chain seqno. 744 return t.notifyNoChainChange(ctx, keybase1.TeamChangeSet{KeyRotated: true}) 745 } 746 747 func teamAdminToSig3ChainLocation(admin *SCTeamAdmin) (*sig3.ChainLocation, error) { 748 if admin == nil { 749 return nil, nil 750 } 751 id, err := admin.TeamID.ToTeamID() 752 if err != nil { 753 return nil, err 754 } 755 s3id, err := sig3.ImportTeamID(id) 756 if err != nil { 757 return nil, err 758 } 759 return &sig3.ChainLocation{ 760 TeamID: *s3id, 761 Seqno: admin.Seqno, 762 ChainType: admin.SeqType, 763 }, nil 764 765 } 766 767 func (t *Team) rotateHiddenGenerateSigMultiItem(mctx libkb.MetaContext, section SCTeamSection, mr *libkb.MerkleRoot) (ret *libkb.SigMultiItem, ratchets *keybase1.HiddenTeamChainRatchetSet, err error) { 768 769 currentSeqno := t.CurrentSeqno() 770 lastLinkID := t.chain().GetLatestLinkID() 771 772 mainChainPrev := keybase1.LinkTriple{ 773 Seqno: currentSeqno, 774 SeqType: keybase1.SeqType_SEMIPRIVATE, 775 LinkID: lastLinkID, 776 } 777 778 me, err := loadMeForSignatures(mctx.Ctx(), mctx.G()) 779 if err != nil { 780 return nil, nil, err 781 } 782 deviceSigningKey, err := t.G().ActiveDevice.SigningKey() 783 if err != nil { 784 return nil, nil, err 785 } 786 hiddenPrev, err := t.G().GetHiddenTeamChainManager().Tail(mctx, t.ID) 787 if err != nil { 788 return nil, nil, err 789 } 790 791 sk, err := t.keyManager.SigningKey() 792 if err != nil { 793 return nil, nil, err 794 } 795 796 ek, err := t.keyManager.EncryptionKey() 797 if err != nil { 798 return nil, nil, err 799 } 800 801 admin, err := teamAdminToSig3ChainLocation(section.Admin) 802 if err != nil { 803 return nil, nil, err 804 } 805 806 ret, ratchets, err = hidden.GenerateKeyRotation(mctx, hidden.GenerateKeyRotationParams{ 807 TeamID: t.ID, 808 IsPublic: t.IsPublic(), 809 IsImplicit: t.IsImplicit(), 810 MerkleRoot: mr, 811 Me: me, 812 SigningKey: deviceSigningKey, 813 MainPrev: mainChainPrev, 814 HiddenPrev: hiddenPrev, 815 Gen: t.keyManager.Generation(), 816 NewSigningKey: sk, 817 NewEncryptionKey: ek, 818 Check: t.keyManager.Check(), 819 Admin: admin, 820 }) 821 822 return ret, ratchets, err 823 } 824 825 func (t *Team) isAdminOrOwner(m keybase1.UserVersion) (res bool, err error) { 826 role, err := t.chain().GetUserRole(m) 827 if err != nil { 828 return false, err 829 } 830 if role.IsAdminOrAbove() { 831 res = true 832 } 833 return res, nil 834 } 835 836 func (t *Team) getDowngradedUsers(ctx context.Context, ms *memberSet) (uids []keybase1.UID, err error) { 837 838 for _, member := range ms.None { 839 // Load member first to check if their eldest_seqno has not changed. 840 // If it did, the member was nuked and we do not need to lease. 841 _, err := loadMember(ctx, t.G(), member.version, true) 842 switch err.(type) { 843 case nil: 844 case libkb.AccountResetError: 845 continue 846 default: 847 return nil, err 848 } 849 850 uids = append(uids, member.version.Uid) 851 } 852 853 for _, member := range ms.nonAdmins() { 854 admin, err := t.isAdminOrOwner(member.version) 855 if err != nil { 856 return nil, err 857 } 858 if admin { 859 uids = append(uids, member.version.Uid) 860 } 861 } 862 863 return uids, nil 864 } 865 866 type ChangeMembershipOptions struct { 867 // Pass "permanent" flag, user will not be able to request access 868 // to the team again, admin will have to add them back. 869 Permanent bool 870 871 // Do not rotate team key, even on member removals. Server will 872 // queue CLKR if client sends removals without rotation. 873 SkipKeyRotation bool 874 } 875 876 func (t *Team) ChangeMembershipWithOptions(ctx context.Context, req keybase1.TeamChangeReq, opts ChangeMembershipOptions) (err error) { 877 defer t.G().CTrace(ctx, "Team.ChangeMembershipWithOptions", &err)() 878 879 if t.IsSubteam() && len(req.Owners) > 0 { 880 return NewSubteamOwnersError() 881 } 882 883 // create the change membership section + secretBoxes 884 section, secretBoxes, implicitAdminBoxes, teamEKPayload, memberSet, ratchet, err := t.changeMembershipSection(ctx, req, opts.SkipKeyRotation) 885 if err != nil { 886 return err 887 } 888 889 if err := t.ForceMerkleRootUpdate(ctx); err != nil { 890 return err 891 } 892 893 var merkleRoot *libkb.MerkleRoot 894 var lease *libkb.Lease 895 896 downgrades, err := t.getDowngradedUsers(ctx, memberSet) 897 if err != nil { 898 return err 899 } 900 901 if len(downgrades) != 0 { 902 lease, merkleRoot, err = libkb.RequestDowngradeLeaseByTeam(ctx, t.G(), t.ID, downgrades) 903 if err != nil { 904 return err 905 } 906 defer func() { 907 // We must cancel in the case of an error in postMulti, but it's safe to cancel 908 // if everything worked. So we always cancel the lease on the way out of this function. 909 // See CORE-6473 for a case in which this was needed. And also the test 910 // `TestOnlyOwnerLeaveThenUpgradeFriend`. 911 err := libkb.CancelDowngradeLease(ctx, t.G(), lease.LeaseID) 912 if err != nil { 913 t.G().Log.CWarningf(ctx, "Failed to cancel downgrade lease: %s", err.Error()) 914 } 915 }() 916 } 917 // post the change to the server 918 sigPayloadArgs := sigPayloadArgs{ 919 secretBoxes: secretBoxes, 920 implicitAdminBoxes: implicitAdminBoxes, 921 lease: lease, 922 teamEKPayload: teamEKPayload, 923 ratchetBlindingKeys: ratchet.ToSigPayload(), 924 } 925 926 if opts.Permanent { 927 sigPayloadArgs.prePayload = libkb.JSONPayload{"permanent": true} 928 } 929 930 // Add a ChangeMembership section and possibly a BotSettings section. 931 sections := []teamSectionWithLinkType{ 932 { 933 linkType: libkb.LinkTypeChangeMembership, 934 section: section, 935 }, 936 } 937 938 // If we are adding any restricted bots add a bot_settings link 939 if len(req.RestrictedBots) > 0 { 940 section, _, err := t.botSettingsSection(ctx, req.RestrictedBots, ratchet, merkleRoot) 941 if err != nil { 942 return err 943 } 944 sections = append(sections, teamSectionWithLinkType{ 945 linkType: libkb.LinkTypeTeamBotSettings, 946 section: section, 947 }) 948 } 949 950 payload, latestSeqno, err := t.changeItemsPayload(ctx, sections, merkleRoot, sigPayloadArgs) 951 if err != nil { 952 return err 953 } 954 955 var recipients, botRecipients []keybase1.UserVersion 956 for uv := range memberSet.recipients { 957 recipients = append(recipients, uv) 958 } 959 for uv := range memberSet.restrictedBotRecipients { 960 botRecipients = append(botRecipients, uv) 961 } 962 newMemSet := newMemberSet() 963 _, err = newMemSet.loadGroup(ctx, t.G(), recipients, storeMemberKindRecipient, true) 964 if err != nil { 965 return err 966 } 967 _, err = newMemSet.loadGroup(ctx, t.G(), botRecipients, storeMemberKindRestrictedBotRecipient, true) 968 if err != nil { 969 return err 970 } 971 if !memberSet.recipients.Eq(newMemSet.recipients) { 972 return BoxRaceError{inner: fmt.Errorf("team box summary changed during sig creation; retry required")} 973 } 974 975 err = t.postMulti(libkb.NewMetaContext(ctx, t.G()), payload) 976 if err != nil { 977 return err 978 } 979 980 err = t.notify(ctx, keybase1.TeamChangeSet{MembershipChanged: true}, latestSeqno) 981 if err != nil { 982 return err 983 } 984 t.storeTeamEKPayload(ctx, teamEKPayload) 985 createTeambotKeys(t.G(), t.ID, memberSet.restrictedBotRecipientUids()) 986 987 return nil 988 } 989 990 func (t *Team) ChangeMembership(ctx context.Context, req keybase1.TeamChangeReq) error { 991 return t.ChangeMembershipWithOptions(ctx, req, ChangeMembershipOptions{}) 992 } 993 994 func (t *Team) downgradeIfOwnerOrAdmin(ctx context.Context) (needsReload bool, err error) { 995 defer t.G().CTrace(ctx, "Team#downgradeIfOwnerOrAdmin", &err)() 996 997 uv, err := t.currentUserUV(ctx) 998 if err != nil { 999 return false, err 1000 } 1001 1002 role, err := t.MemberRole(ctx, uv) 1003 if err != nil { 1004 return false, err 1005 } 1006 1007 if role.IsAdminOrAbove() { 1008 reqs := keybase1.TeamChangeReq{Writers: []keybase1.UserVersion{uv}} 1009 if err := t.ChangeMembership(ctx, reqs); err != nil { 1010 return false, err 1011 } 1012 1013 return true, nil 1014 } 1015 1016 return false, nil 1017 } 1018 1019 func (t *Team) makeRatchet(ctx context.Context) (ret *hidden.Ratchet, err error) { 1020 return t.chain().makeHiddenRatchet(libkb.NewMetaContext(ctx, t.G())) 1021 } 1022 1023 func (t *Team) Leave(ctx context.Context, permanent bool) error { 1024 // If we are owner or admin, we have to downgrade ourselves first. 1025 needsReload, err := t.downgradeIfOwnerOrAdmin(ctx) 1026 if err != nil { 1027 return err 1028 } 1029 if needsReload { 1030 t, err = Load(ctx, t.G(), keybase1.LoadTeamArg{ 1031 ID: t.ID, 1032 Public: t.IsPublic(), 1033 ForceRepoll: true, 1034 }) 1035 if err != nil { 1036 return err 1037 } 1038 } 1039 1040 // Check if we are an implicit admin with no explicit membership 1041 // in order to give a nice error. 1042 role, err := t.myRole(ctx) 1043 if err != nil { 1044 role = keybase1.TeamRole_NONE 1045 } 1046 if role == keybase1.TeamRole_NONE { 1047 _, err := t.getAdminPermission(ctx) 1048 switch err.(type) { 1049 case nil, *AdminPermissionRequiredError: 1050 return NewImplicitAdminCannotLeaveError() 1051 } 1052 } 1053 1054 ratchet, err := t.makeRatchet(ctx) 1055 if err != nil { 1056 return err 1057 } 1058 1059 section := SCTeamSection{ 1060 ID: SCTeamID(t.ID), 1061 Implicit: t.IsImplicit(), 1062 Public: t.IsPublic(), 1063 Ratchets: ratchet.ToTeamSection(), 1064 } 1065 1066 sigPayloadArgs := sigPayloadArgs{ 1067 prePayload: libkb.JSONPayload{"permanent": permanent}, 1068 ratchetBlindingKeys: ratchet.ToSigPayload(), 1069 } 1070 latestSeqno, err := t.postChangeItem(ctx, section, libkb.LinkTypeLeave, nil, sigPayloadArgs) 1071 if err != nil { 1072 return err 1073 } 1074 1075 return t.notify(ctx, keybase1.TeamChangeSet{MembershipChanged: true}, latestSeqno) 1076 } 1077 1078 func (t *Team) deleteRoot(ctx context.Context) error { 1079 m := t.MetaContext(ctx) 1080 uv, err := t.currentUserUV(ctx) 1081 if err != nil { 1082 return err 1083 } 1084 1085 role, err := t.MemberRole(ctx, uv) 1086 if err != nil { 1087 return err 1088 } 1089 1090 if role != keybase1.TeamRole_OWNER { 1091 return libkb.AppStatusError{ 1092 Code: int(keybase1.StatusCode_SCTeamSelfNotOwner), 1093 Name: "SELF_NOT_OWNER", 1094 Desc: "You must be an owner to delete a team", 1095 } 1096 } 1097 1098 ratchet, err := t.makeRatchet(ctx) 1099 if err != nil { 1100 return err 1101 } 1102 1103 teamSection := SCTeamSection{ 1104 ID: SCTeamID(t.ID), 1105 Implicit: t.IsImplicit(), 1106 Public: t.IsPublic(), 1107 Ratchets: ratchet.ToTeamSection(), 1108 } 1109 1110 mr, err := t.G().MerkleClient.FetchRootFromServer(t.MetaContext(ctx), libkb.TeamMerkleFreshnessForAdmin) 1111 if err != nil { 1112 return err 1113 } 1114 if mr == nil { 1115 return errors.New("No merkle root available for team delete root") 1116 } 1117 1118 sigMultiItem, latestSeqno, err := t.sigTeamItem(ctx, teamSection, libkb.LinkTypeDeleteRoot, mr) 1119 if err != nil { 1120 return err 1121 } 1122 1123 sigPayloadArgs := sigPayloadArgs{ 1124 ratchetBlindingKeys: ratchet.ToSigPayload(), 1125 } 1126 payload := t.sigPayload([]libkb.SigMultiItem{sigMultiItem}, sigPayloadArgs) 1127 err = t.postMulti(m, payload) 1128 if err != nil { 1129 return err 1130 } 1131 return t.HintLatestSeqno(m, latestSeqno) 1132 } 1133 1134 func (t *Team) deleteSubteam(ctx context.Context) error { 1135 m := t.MetaContext(ctx) 1136 1137 // subteam delete consists of two links: 1138 // 1. delete_subteam in parent chain 1139 // 2. delete_up_pointer in subteam chain 1140 1141 if t.IsImplicit() { 1142 return fmt.Errorf("unsupported delete of implicit subteam") 1143 } 1144 1145 parentID := t.chain().GetParentID() 1146 parentTeam, err := Load(ctx, t.G(), keybase1.LoadTeamArg{ 1147 ID: *parentID, 1148 Public: t.IsPublic(), 1149 ForceRepoll: true, 1150 }) 1151 switch { 1152 case err == nil: 1153 case IsTeamReadError(err): 1154 return fmt.Errorf("failed to load parent team; you must be an admin of a parent team to delete a subteam: %w", err) 1155 default: 1156 return fmt.Errorf("failed to load parent team: %w", err) 1157 } 1158 1159 admin, err := parentTeam.getAdminPermission(ctx) 1160 switch err.(type) { 1161 case nil: 1162 case *AdminPermissionRequiredError: 1163 return fmt.Errorf("failed to get admin permission from parent team; you must be an admin of a parent team to delete a subteam: %w", err) 1164 default: 1165 return fmt.Errorf("failed to get admin permission from parent team: %w", err) 1166 } 1167 1168 subteamName := SCTeamName(t.Data.Name.String()) 1169 1170 entropy, err := makeSCTeamEntropy() 1171 if err != nil { 1172 return err 1173 } 1174 parentRatchet, err := parentTeam.makeRatchet(ctx) 1175 if err != nil { 1176 return err 1177 } 1178 parentSection := SCTeamSection{ 1179 ID: SCTeamID(parentTeam.ID), 1180 Subteam: &SCSubteam{ 1181 ID: SCTeamID(t.ID), 1182 Name: subteamName, // weird this is required 1183 }, 1184 Admin: admin, 1185 Public: t.IsPublic(), 1186 Entropy: entropy, 1187 Ratchets: parentRatchet.ToTeamSection(), 1188 } 1189 1190 mr, err := t.G().MerkleClient.FetchRootFromServer(t.MetaContext(ctx), libkb.TeamMerkleFreshnessForAdmin) 1191 if err != nil { 1192 return err 1193 } 1194 if mr == nil { 1195 return errors.New("No merkle root available for team delete subteam") 1196 } 1197 1198 sigParent, _, err := parentTeam.sigTeamItem(ctx, parentSection, libkb.LinkTypeDeleteSubteam, mr) 1199 if err != nil { 1200 return err 1201 } 1202 1203 subRatchet, err := t.makeRatchet(ctx) 1204 if err != nil { 1205 return err 1206 } 1207 subSection := SCTeamSection{ 1208 ID: SCTeamID(t.ID), 1209 Name: &subteamName, // weird this is required 1210 Parent: &SCTeamParent{ 1211 ID: SCTeamID(parentTeam.ID), 1212 Seqno: parentTeam.chain().GetLatestSeqno() + 1, // the seqno of the *new* parent link 1213 SeqType: seqTypeForTeamPublicness(parentTeam.IsPublic()), 1214 }, 1215 Public: t.IsPublic(), 1216 Admin: admin, 1217 Ratchets: subRatchet.ToTeamSection(), 1218 } 1219 sigSub, latestSeqno, err := t.sigTeamItem(ctx, subSection, libkb.LinkTypeDeleteUpPointer, mr) 1220 if err != nil { 1221 return err 1222 } 1223 1224 payload := make(libkb.JSONPayload) 1225 payload["sigs"] = []interface{}{sigParent, sigSub} 1226 1227 var ratchetSet hidden.RatchetBlindingKeySet 1228 if parentRatchet != nil { 1229 ratchetSet.Add(*parentRatchet) 1230 } 1231 if subRatchet != nil { 1232 ratchetSet.Add(*subRatchet) 1233 } 1234 err = ratchetSet.AddToJSONPayload(payload) 1235 if err != nil { 1236 return err 1237 } 1238 1239 err = t.postMulti(m, payload) 1240 if err != nil { 1241 return err 1242 } 1243 return t.HintLatestSeqno(m, latestSeqno) 1244 } 1245 1246 func (t *Team) NumActiveInvites() int { 1247 return t.chain().NumActiveInvites() 1248 } 1249 1250 func (t *Team) HasActiveInvite(mctx libkb.MetaContext, name keybase1.TeamInviteName, typ string) (bool, error) { 1251 it, err := TeamInviteTypeFromString(mctx, typ) 1252 if err != nil { 1253 return false, err 1254 } 1255 return t.chain().HasActiveInvite(name, it) 1256 } 1257 1258 func (t *Team) FindActiveKeybaseInvite(uid keybase1.UID) (keybase1.TeamInvite, keybase1.UserVersion, bool) { 1259 return t.chain().FindActiveKeybaseInvite(uid) 1260 } 1261 1262 func (t *Team) GetActiveAndObsoleteInvites() (ret map[keybase1.TeamInviteID]keybase1.TeamInvite) { 1263 ret = make(map[keybase1.TeamInviteID]keybase1.TeamInvite) 1264 for inviteID, inviteMD := range t.chain().inner.InviteMetadatas { 1265 code, err := inviteMD.Status.Code() 1266 if err != nil { 1267 continue 1268 } 1269 switch code { 1270 case keybase1.TeamInviteMetadataStatusCode_ACTIVE, keybase1.TeamInviteMetadataStatusCode_OBSOLETE: 1271 ret[inviteID] = inviteMD.Invite 1272 } 1273 } 1274 return ret 1275 } 1276 1277 // If uv.Uid is set, then username is ignored. 1278 // Otherwise resolvedUsername and uv are ignored. 1279 func (t *Team) InviteMember(ctx context.Context, username string, role keybase1.TeamRole, resolvedUsername libkb.NormalizedUsername, uv keybase1.UserVersion) (keybase1.TeamAddMemberResult, error) { 1280 // if a user version was previously loaded, then there is a keybase user for username, but 1281 // without a PUK or without any keys. 1282 if uv.Uid.Exists() { 1283 return t.inviteKeybaseMember(libkb.NewMetaContext(ctx, t.G()), uv, role, resolvedUsername) 1284 } 1285 1286 // If a social, or email, or other type of invite, assert it's not an owner. 1287 if role.IsOrAbove(keybase1.TeamRole_OWNER) { 1288 return keybase1.TeamAddMemberResult{}, errors.New("You cannot invite an owner to a team.") 1289 } 1290 1291 return t.inviteSBSMember(ctx, username, role) 1292 } 1293 1294 func (t *Team) InviteEmailPhoneMember(ctx context.Context, name string, role keybase1.TeamRole, typ string) error { 1295 t.G().Log.CDebugf(ctx, "team %s invite %s member %s", t.Name(), typ, name) 1296 1297 if role == keybase1.TeamRole_OWNER { 1298 return errors.New("You cannot invite an owner to a team over email.") 1299 } 1300 1301 invite := SCTeamInvite{ 1302 Type: typ, 1303 Name: keybase1.TeamInviteName(name), 1304 ID: NewInviteID(), 1305 } 1306 return t.postInvite(ctx, invite, role) 1307 } 1308 1309 func (t *Team) inviteKeybaseMember(mctx libkb.MetaContext, uv keybase1.UserVersion, role keybase1.TeamRole, resolvedUsername libkb.NormalizedUsername) (res keybase1.TeamAddMemberResult, err error) { 1310 mctx.Debug("team %s invite keybase member %s", t.Name(), uv) 1311 1312 invite := SCTeamInvite{ 1313 Type: "keybase", 1314 Name: uv.TeamInviteName(), 1315 ID: NewInviteID(), 1316 } 1317 1318 existing, err := t.HasActiveInvite(mctx, invite.Name, invite.Type) 1319 if err != nil { 1320 return res, err 1321 } 1322 1323 if existing { 1324 return res, libkb.ExistsError{Msg: "An invite for this user already exists."} 1325 } 1326 1327 if t.IsSubteam() && role == keybase1.TeamRole_OWNER { 1328 return res, NewSubteamOwnersError() 1329 } 1330 1331 invList := []SCTeamInvite{invite} 1332 cancelList := []SCTeamInviteID{} 1333 1334 var invites SCTeamInvites 1335 switch role { 1336 case keybase1.TeamRole_ADMIN: 1337 invites.Admins = &invList 1338 case keybase1.TeamRole_WRITER: 1339 invites.Writers = &invList 1340 case keybase1.TeamRole_READER: 1341 invites.Readers = &invList 1342 case keybase1.TeamRole_OWNER: 1343 invites.Owners = &invList 1344 } 1345 1346 // Inviting keybase PUKless member has to remove old invites for that 1347 // uid first, or it will bounce off the server with an error. There is 1348 // no hard limit in team player to disallow multiple keybase invites 1349 // for the same UID, but there is a soft serverside check when 1350 // signature is posted. 1351 for inviteID, existingInvite := range t.GetActiveAndObsoleteInvites() { 1352 // KeybaseUserVersion checks if invite is KEYBASE and errors 1353 // if not, we can blindly call it for all invites, and continue 1354 // to next one if we get an error. 1355 existingUV, err := existingInvite.KeybaseUserVersion() 1356 if err != nil { 1357 continue 1358 } 1359 1360 if existingUV.Uid != uv.Uid { 1361 continue 1362 } 1363 1364 if uv.EldestSeqno != 0 && existingUV.EldestSeqno > uv.EldestSeqno { 1365 // We probably know invitee by their outdated EldestSeqno. There 1366 // is also a server check for this case. 1367 return res, libkb.ExistsError{ 1368 Msg: fmt.Sprintf("An invite for this user already exists, with higher EldestSeqno (%d > %d)", existingUV.EldestSeqno, uv.EldestSeqno), 1369 } 1370 } 1371 1372 mctx.Debug("Canceling old Keybase invite: %+v", existingInvite) 1373 cancelList = append(cancelList, SCTeamInviteID(inviteID)) 1374 } 1375 1376 if len(cancelList) != 0 { 1377 mctx.Debug("Total %d old invites will be canceled.", len(cancelList)) 1378 invites.Cancel = &cancelList 1379 } 1380 1381 mctx.Debug("Adding invite: %+v", invite) 1382 if err := t.postTeamInvites(mctx.Ctx(), invites); err != nil { 1383 return res, err 1384 } 1385 return keybase1.TeamAddMemberResult{Invited: true, User: &keybase1.User{Uid: uv.Uid, Username: resolvedUsername.String()}}, nil 1386 } 1387 1388 func (t *Team) inviteSBSMember(ctx context.Context, username string, role keybase1.TeamRole) (keybase1.TeamAddMemberResult, error) { 1389 // parse username to get social 1390 typ, name, err := parseSocialAssertion(libkb.NewMetaContext(ctx, t.G()), username) 1391 if err != nil { 1392 return keybase1.TeamAddMemberResult{}, err 1393 } 1394 t.G().Log.CDebugf(ctx, "team %s invite sbs member %s/%s", t.Name(), typ, name) 1395 1396 invite := SCTeamInvite{ 1397 Type: typ, 1398 Name: keybase1.TeamInviteName(name), 1399 ID: NewInviteID(), 1400 } 1401 1402 if err := t.postInvite(ctx, invite, role); err != nil { 1403 return keybase1.TeamAddMemberResult{}, err 1404 } 1405 1406 return keybase1.TeamAddMemberResult{Invited: true}, nil 1407 } 1408 1409 func (t *Team) InviteSeitan(ctx context.Context, role keybase1.TeamRole, label keybase1.SeitanKeyLabel) (ikey SeitanIKey, err error) { 1410 defer t.G().CTrace(ctx, fmt.Sprintf("InviteSeitan: team: %v, role: %v", t.Name(), role), &err)() 1411 1412 ikey, err = GenerateIKey() 1413 if err != nil { 1414 return ikey, err 1415 } 1416 1417 sikey, err := ikey.GenerateSIKey() 1418 if err != nil { 1419 return ikey, err 1420 } 1421 1422 inviteID, err := sikey.GenerateTeamInviteID() 1423 if err != nil { 1424 return ikey, err 1425 } 1426 1427 _, encoded, err := ikey.GeneratePackedEncryptedKey(ctx, t, label) 1428 if err != nil { 1429 return ikey, err 1430 } 1431 1432 invite := SCTeamInvite{ 1433 Type: "seitan_invite_token", 1434 Name: keybase1.TeamInviteName(encoded), 1435 ID: inviteID, 1436 } 1437 1438 if err := t.postInvite(ctx, invite, role); err != nil { 1439 return ikey, err 1440 } 1441 1442 return ikey, err 1443 } 1444 1445 func (t *Team) InviteSeitanV2(ctx context.Context, role keybase1.TeamRole, label keybase1.SeitanKeyLabel) (ikey SeitanIKeyV2, err error) { 1446 defer t.G().CTrace(ctx, fmt.Sprintf("InviteSeitanV2: team: %v, role: %v", t.Name(), role), &err)() 1447 1448 ikey, err = GenerateIKeyV2() 1449 if err != nil { 1450 return ikey, err 1451 } 1452 1453 sikey, err := ikey.GenerateSIKey() 1454 if err != nil { 1455 return ikey, err 1456 } 1457 1458 inviteID, err := sikey.GenerateTeamInviteID() 1459 if err != nil { 1460 return ikey, err 1461 } 1462 1463 _, encoded, err := sikey.GeneratePackedEncryptedKey(ctx, t, label) 1464 if err != nil { 1465 return ikey, err 1466 } 1467 1468 invite := SCTeamInvite{ 1469 Type: "seitan_invite_token", 1470 Name: keybase1.TeamInviteName(encoded), 1471 ID: inviteID, 1472 } 1473 1474 if err := t.postInvite(ctx, invite, role); err != nil { 1475 return ikey, err 1476 } 1477 1478 return ikey, err 1479 } 1480 1481 func (t *Team) InviteInvitelink( 1482 ctx context.Context, 1483 role keybase1.TeamRole, 1484 maxUses keybase1.TeamInviteMaxUses, 1485 etime *keybase1.UnixTime, 1486 ) (ikey keybase1.SeitanIKeyInvitelink, inviteID SCTeamInviteID, err error) { 1487 defer t.G().CTrace(ctx, fmt.Sprintf("InviteInviteLink: team: %v, role: %v, etime: %v, maxUses: %v", t.Name(), role, etime, maxUses), &err)() 1488 1489 if role.IsAdminOrAbove() { 1490 return ikey, inviteID, fmt.Errorf("cannot create invitelink to add as %v", role) 1491 } 1492 1493 ikey, err = GenerateSeitanIKeyInvitelink() 1494 if err != nil { 1495 return ikey, inviteID, err 1496 } 1497 1498 sikey, err := GenerateSIKeyInvitelink(ikey) 1499 if err != nil { 1500 return ikey, inviteID, err 1501 } 1502 1503 inviteID, err = sikey.GenerateTeamInviteID() 1504 if err != nil { 1505 return ikey, inviteID, err 1506 } 1507 1508 // label is hardcoded for now, but could change in the future 1509 label := keybase1.NewSeitanKeyLabelWithGeneric(keybase1.SeitanKeyLabelGeneric{L: "link"}) 1510 1511 _, encoded, err := GeneratePackedEncryptedKeyInvitelink(ctx, ikey, t, label) 1512 if err != nil { 1513 return ikey, inviteID, err 1514 } 1515 1516 invite := SCTeamInvite{ 1517 Type: "invitelink", 1518 Name: keybase1.TeamInviteName(encoded), 1519 ID: inviteID, 1520 Etime: etime, 1521 MaxUses: &maxUses, 1522 } 1523 1524 if err := t.postInvite(ctx, invite, role); err != nil { 1525 return ikey, inviteID, err 1526 } 1527 1528 return ikey, inviteID, err 1529 } 1530 1531 func (t *Team) postInvite(ctx context.Context, invite SCTeamInvite, role keybase1.TeamRole) error { 1532 existing, err := t.HasActiveInvite(t.MetaContext(ctx), invite.Name, invite.Type) 1533 if err != nil { 1534 return err 1535 } 1536 if existing { 1537 return libkb.ExistsError{Msg: "An invite for this user already exists."} 1538 } 1539 1540 if t.IsSubteam() && role == keybase1.TeamRole_OWNER { 1541 return NewSubteamOwnersError() 1542 } 1543 1544 invList := []SCTeamInvite{invite} 1545 var invites SCTeamInvites 1546 switch role { 1547 case keybase1.TeamRole_RESTRICTEDBOT, keybase1.TeamRole_BOT: 1548 return fmt.Errorf("bot roles disallowed for invites") 1549 case keybase1.TeamRole_READER: 1550 invites.Readers = &invList 1551 case keybase1.TeamRole_WRITER: 1552 invites.Writers = &invList 1553 case keybase1.TeamRole_ADMIN: 1554 invites.Admins = &invList 1555 case keybase1.TeamRole_OWNER: 1556 invites.Owners = &invList 1557 } 1558 if invites.Len() == 0 { 1559 return fmt.Errorf("invalid invite, 0 members invited") 1560 } 1561 1562 return t.postTeamInvites(ctx, invites) 1563 } 1564 1565 func (t *Team) postTeamInvites(ctx context.Context, invites SCTeamInvites) error { 1566 m := t.MetaContext(ctx) 1567 1568 admin, err := t.getAdminPermission(ctx) 1569 if err != nil { 1570 return err 1571 } 1572 1573 if t.IsSubteam() && invites.Owners != nil && len(*invites.Owners) > 0 { 1574 return NewSubteamOwnersError() 1575 } 1576 1577 entropy, err := makeSCTeamEntropy() 1578 if err != nil { 1579 return err 1580 } 1581 1582 ratchet, err := t.makeRatchet(ctx) 1583 if err != nil { 1584 return err 1585 } 1586 1587 teamSection := SCTeamSection{ 1588 ID: SCTeamID(t.ID), 1589 Admin: admin, 1590 Invites: &invites, 1591 Implicit: t.IsImplicit(), 1592 Public: t.IsPublic(), 1593 Entropy: entropy, 1594 Ratchets: ratchet.ToTeamSection(), 1595 } 1596 1597 mr, err := t.G().MerkleClient.FetchRootFromServer(t.MetaContext(ctx), libkb.TeamMerkleFreshnessForAdmin) 1598 if err != nil { 1599 return err 1600 } 1601 if mr == nil { 1602 return errors.New("No merkle root available for team invite") 1603 } 1604 1605 sigMultiItem, latestSeqno, err := t.sigTeamItem(ctx, teamSection, libkb.LinkTypeInvite, mr) 1606 if err != nil { 1607 return err 1608 } 1609 1610 sigMulti := []libkb.SigMultiItem{sigMultiItem} 1611 err = t.precheckLinksToPost(ctx, sigMulti) 1612 if err != nil { 1613 return err 1614 } 1615 1616 sigPayloadArgs := sigPayloadArgs{ 1617 ratchetBlindingKeys: ratchet.ToSigPayload(), 1618 } 1619 1620 payload := t.sigPayload(sigMulti, sigPayloadArgs) 1621 err = t.postMulti(m, payload) 1622 if err != nil { 1623 return err 1624 } 1625 1626 return t.notify(ctx, keybase1.TeamChangeSet{MembershipChanged: true}, latestSeqno) 1627 } 1628 1629 // NOTE since this function uses `Load` and not `load2`, readSubteamID cannot 1630 // be passed through, this call will fail if a user is not a member of the 1631 // parent team (or child of the parent team) for which the validator validates 1632 func (t *Team) traverseUpUntil(ctx context.Context, validator func(t *Team) bool) (targetTeam *Team, err error) { 1633 targetTeam = t 1634 for { 1635 if validator(targetTeam) { 1636 return targetTeam, nil 1637 } 1638 parentID := targetTeam.chain().GetParentID() 1639 if parentID == nil { 1640 return nil, nil 1641 } 1642 targetTeam, err = Load(ctx, t.G(), keybase1.LoadTeamArg{ 1643 ID: *parentID, 1644 Public: parentID.IsPublic(), 1645 // This is in a cold path anyway, so might as well trade reliability 1646 // at the expense of speed. 1647 ForceRepoll: true, 1648 }) 1649 if err != nil { 1650 return nil, err 1651 } 1652 } 1653 } 1654 1655 func (t *Team) getAdminPermission(ctx context.Context) (admin *SCTeamAdmin, err error) { 1656 uv, err := t.currentUserUV(ctx) 1657 if err != nil { 1658 return nil, err 1659 } 1660 1661 targetTeam, err := t.traverseUpUntil(ctx, func(s *Team) bool { 1662 return s.chain().GetAdminUserLogPoint(uv) != nil 1663 }) 1664 if err != nil { 1665 return nil, err 1666 } 1667 if targetTeam == nil { 1668 return nil, NewAdminPermissionRequiredError() 1669 } 1670 1671 logPoint := targetTeam.chain().GetAdminUserLogPoint(uv) 1672 ret := SCTeamAdmin{ 1673 TeamID: SCTeamID(targetTeam.ID), 1674 Seqno: logPoint.SigMeta.SigChainLocation.Seqno, 1675 SeqType: logPoint.SigMeta.SigChainLocation.SeqType, 1676 } 1677 return &ret, nil 1678 } 1679 1680 func (t *Team) changeMembershipSection(ctx context.Context, req keybase1.TeamChangeReq, skipKeyRotation bool) (SCTeamSection, *PerTeamSharedSecretBoxes, map[keybase1.TeamID]*PerTeamSharedSecretBoxes, *teamEKPayload, *memberSet, *hidden.Ratchet, error) { 1681 // initialize key manager 1682 if _, err := t.SharedSecret(ctx); err != nil { 1683 return SCTeamSection{}, nil, nil, nil, nil, nil, err 1684 } 1685 1686 admin, err := t.getAdminPermission(ctx) 1687 if err != nil { 1688 return SCTeamSection{}, nil, nil, nil, nil, nil, err 1689 } 1690 1691 if t.IsSubteam() && len(req.Owners) > 0 { 1692 return SCTeamSection{}, nil, nil, nil, nil, nil, NewSubteamOwnersError() 1693 } 1694 1695 // load the member set specified in req 1696 memSet, err := newMemberSetChange(ctx, t.G(), req) 1697 if err != nil { 1698 return SCTeamSection{}, nil, nil, nil, nil, nil, err 1699 } 1700 1701 ratchet, err := t.makeRatchet(ctx) 1702 if err != nil { 1703 return SCTeamSection{}, nil, nil, nil, nil, nil, err 1704 } 1705 1706 section := SCTeamSection{ 1707 ID: SCTeamID(t.ID), 1708 Admin: admin, 1709 Implicit: t.IsImplicit(), 1710 Public: t.IsPublic(), 1711 Ratchets: ratchet.ToTeamSection(), 1712 } 1713 1714 section.Members, err = memSet.Section() 1715 if err != nil { 1716 return SCTeamSection{}, nil, nil, nil, nil, nil, err 1717 } 1718 1719 // create secret boxes for recipients, possibly rotating the key 1720 secretBoxes, implicitAdminBoxes, perTeamKeySection, teamEKPayload, err := t.recipientBoxes(ctx, memSet, skipKeyRotation) 1721 if err != nil { 1722 return SCTeamSection{}, nil, nil, nil, nil, nil, err 1723 } 1724 1725 section.PerTeamKey = perTeamKeySection 1726 1727 err = addSummaryHash(§ion, secretBoxes) 1728 if err != nil { 1729 return SCTeamSection{}, nil, nil, nil, nil, nil, err 1730 } 1731 1732 section.CompletedInvites = req.CompletedInvites 1733 section.UsedInvites = makeSCMapInviteIDUVMap(req.UsedInvites) 1734 1735 section.Implicit = t.IsImplicit() 1736 section.Public = t.IsPublic() 1737 1738 if len(section.CompletedInvites) > 0 && section.Members == nil { 1739 // Just mooted invites is fine - if TeamChangeReq is empty, 1740 // changeMembershipSection returned nil members. But we need 1741 // empty Members in order to have a valid link. 1742 section.Members = &SCTeamMembers{} 1743 } 1744 1745 return section, secretBoxes, implicitAdminBoxes, teamEKPayload, memSet, ratchet, nil 1746 } 1747 1748 func (t *Team) changeItemsPayload(ctx context.Context, sections []teamSectionWithLinkType, 1749 merkleRoot *libkb.MerkleRoot, sigPayloadArgs sigPayloadArgs) (libkb.JSONPayload, keybase1.Seqno, error) { 1750 1751 var readySigs []libkb.SigMultiItem 1752 nextSeqno := t.NextSeqno() 1753 latestLinkID := t.chain().GetLatestLinkID() 1754 1755 for _, section := range sections { 1756 sigMultiItem, linkID, err := t.sigTeamItemRaw(ctx, section.section, 1757 section.linkType, nextSeqno, latestLinkID, merkleRoot) 1758 if err != nil { 1759 return nil, keybase1.Seqno(0), err 1760 } 1761 nextSeqno++ 1762 latestLinkID = linkID 1763 readySigs = append(readySigs, sigMultiItem) 1764 } 1765 1766 if err := t.precheckLinksToPost(ctx, readySigs); err != nil { 1767 return nil, keybase1.Seqno(0), err 1768 } 1769 1770 payload := t.sigPayload(readySigs, sigPayloadArgs) 1771 return payload, nextSeqno - 1, nil 1772 } 1773 1774 func (t *Team) changeItemPayload(ctx context.Context, section SCTeamSection, linkType libkb.LinkType, 1775 merkleRoot *libkb.MerkleRoot, sigPayloadArgs sigPayloadArgs) (libkb.JSONPayload, keybase1.Seqno, error) { 1776 // create the change item 1777 sigMultiItem, latestSeqno, err := t.sigTeamItem(ctx, section, linkType, merkleRoot) 1778 if err != nil { 1779 return nil, keybase1.Seqno(0), err 1780 } 1781 1782 sigMulti := []libkb.SigMultiItem{sigMultiItem} 1783 err = t.precheckLinksToPost(ctx, sigMulti) 1784 if err != nil { 1785 return nil, keybase1.Seqno(0), err 1786 } 1787 1788 // make the payload 1789 payload := t.sigPayload(sigMulti, sigPayloadArgs) 1790 return payload, latestSeqno, nil 1791 } 1792 1793 func (t *Team) postChangeItem(ctx context.Context, section SCTeamSection, linkType libkb.LinkType, merkleRoot *libkb.MerkleRoot, sigPayloadArgs sigPayloadArgs) (keybase1.Seqno, error) { 1794 payload, latestSeqno, err := t.changeItemPayload(ctx, section, linkType, merkleRoot, sigPayloadArgs) 1795 if err != nil { 1796 return keybase1.Seqno(0), err 1797 } 1798 // send it to the server 1799 err = t.postMulti(libkb.NewMetaContext(ctx, t.G()), payload) 1800 if err != nil { 1801 return keybase1.Seqno(0), err 1802 } 1803 return latestSeqno, nil 1804 } 1805 1806 func (t *Team) currentUserUV(ctx context.Context) (keybase1.UserVersion, error) { 1807 return t.G().GetMeUV(ctx) 1808 } 1809 1810 func loadMeForSignatures(ctx context.Context, g *libkb.GlobalContext) (libkb.UserForSignatures, error) { 1811 return libkb.LoadSelfForTeamSignatures(ctx, g) 1812 } 1813 1814 func usesPerTeamKeys(linkType libkb.LinkType) bool { 1815 switch linkType { 1816 case libkb.LinkTypeLeave: 1817 return false 1818 case libkb.LinkTypeInvite: 1819 return false 1820 case libkb.LinkTypeDeleteRoot: 1821 return false 1822 case libkb.LinkTypeDeleteSubteam: 1823 return false 1824 case libkb.LinkTypeDeleteUpPointer: 1825 return false 1826 case libkb.LinkTypeKBFSSettings: 1827 return false 1828 } 1829 1830 return true 1831 } 1832 1833 func (t *Team) sigTeamItem(ctx context.Context, section SCTeamSection, linkType libkb.LinkType, merkleRoot *libkb.MerkleRoot) (libkb.SigMultiItem, keybase1.Seqno, error) { 1834 nextSeqno := t.NextSeqno() 1835 lastLinkID := t.chain().GetLatestLinkID() 1836 1837 sig, _, err := t.sigTeamItemRaw(ctx, section, linkType, nextSeqno, lastLinkID, merkleRoot) 1838 return sig, nextSeqno, err 1839 } 1840 1841 func (t *Team) sigTeamItemRaw(ctx context.Context, section SCTeamSection, linkType libkb.LinkType, nextSeqno keybase1.Seqno, lastLinkID keybase1.LinkID, merkleRoot *libkb.MerkleRoot) (libkb.SigMultiItem, keybase1.LinkID, error) { 1842 me, err := loadMeForSignatures(ctx, t.G()) 1843 if err != nil { 1844 return libkb.SigMultiItem{}, "", err 1845 } 1846 deviceSigningKey, err := t.G().ActiveDevice.SigningKey() 1847 if err != nil { 1848 return libkb.SigMultiItem{}, "", err 1849 } 1850 latestLinkID, err := libkb.ImportLinkID(lastLinkID) 1851 if err != nil { 1852 return libkb.SigMultiItem{}, "", err 1853 } 1854 1855 sig, err := ChangeSig(t.G(), me, latestLinkID, nextSeqno, deviceSigningKey, section, linkType, merkleRoot) 1856 if err != nil { 1857 return libkb.SigMultiItem{}, "", err 1858 } 1859 1860 var signingKey libkb.NaclSigningKeyPair 1861 var encryptionKey libkb.NaclDHKeyPair 1862 if usesPerTeamKeys(linkType) { 1863 signingKey, err = t.keyManager.SigningKey() 1864 if err != nil { 1865 return libkb.SigMultiItem{}, "", err 1866 } 1867 encryptionKey, err = t.keyManager.EncryptionKey() 1868 if err != nil { 1869 return libkb.SigMultiItem{}, "", err 1870 } 1871 if section.PerTeamKey != nil { 1872 // need a reverse sig 1873 1874 // set a nil value (not empty) for reverse_sig (fails without this) 1875 err := sig.SetValueAtPath("body.team.per_team_key.reverse_sig", jsonw.NewNil()) 1876 if err != nil { 1877 return libkb.SigMultiItem{}, "", err 1878 } 1879 reverseSig, _, _, err := libkb.SignJSON(sig, signingKey) 1880 if err != nil { 1881 return libkb.SigMultiItem{}, "", err 1882 } 1883 err = sig.SetValueAtPath("body.team.per_team_key.reverse_sig", jsonw.NewString(reverseSig)) 1884 if err != nil { 1885 return libkb.SigMultiItem{}, "", err 1886 } 1887 } 1888 } 1889 1890 seqType := seqTypeForTeamPublicness(t.IsPublic()) 1891 1892 sigJSON, err := sig.Marshal() 1893 if err != nil { 1894 return libkb.SigMultiItem{}, "", err 1895 } 1896 v2Sig, _, newLinkID, err := libkb.MakeSigchainV2OuterSig( 1897 t.MetaContext(ctx), 1898 deviceSigningKey, 1899 linkType, 1900 nextSeqno, 1901 sigJSON, 1902 latestLinkID, 1903 libkb.SigHasRevokes(false), 1904 seqType, 1905 libkb.SigIgnoreIfUnsupported(false), 1906 nil, 1907 ) 1908 if err != nil { 1909 return libkb.SigMultiItem{}, "", err 1910 } 1911 1912 sigMultiItem := libkb.SigMultiItem{ 1913 Sig: v2Sig, 1914 SigningKID: deviceSigningKey.GetKID(), 1915 Type: string(linkType), 1916 SeqType: seqType, 1917 SigInner: string(sigJSON), 1918 TeamID: t.ID, 1919 } 1920 if usesPerTeamKeys(linkType) { 1921 sigMultiItem.PublicKeys = &libkb.SigMultiItemPublicKeys{ 1922 Encryption: encryptionKey.GetKID(), 1923 Signing: signingKey.GetKID(), 1924 } 1925 } 1926 1927 return sigMultiItem, keybase1.LinkID(newLinkID.String()), nil 1928 } 1929 1930 func (t *Team) recipientBoxes(ctx context.Context, memSet *memberSet, skipKeyRotation bool) ( 1931 *PerTeamSharedSecretBoxes, map[keybase1.TeamID]*PerTeamSharedSecretBoxes, 1932 *SCPerTeamKey, *teamEKPayload, error) { 1933 1934 // get device key 1935 deviceEncryptionKey, err := t.G().ActiveDevice.EncryptionKey() 1936 if err != nil { 1937 return nil, nil, nil, nil, err 1938 } 1939 1940 // First create all the subteam per-team-key boxes for new implicit admins. 1941 // We'll return these whether or not we're doing a rotation below. 1942 // TODO: Should we no-op this if the admins+owners aren't actually new? 1943 var implicitAdminBoxes map[keybase1.TeamID]*PerTeamSharedSecretBoxes 1944 adminAndOwnerRecipients := memSet.adminAndOwnerRecipients() 1945 if len(adminAndOwnerRecipients) > 0 { 1946 implicitAdminBoxes = map[keybase1.TeamID]*PerTeamSharedSecretBoxes{} 1947 subteams, err := t.loadAllTransitiveSubteams(ctx, true /*forceRepoll*/) 1948 if err != nil { 1949 return nil, nil, nil, nil, err 1950 } 1951 for _, subteam := range subteams { 1952 subteamBoxes, err := subteam.keyManager.SharedSecretBoxes(t.MetaContext(ctx), deviceEncryptionKey, adminAndOwnerRecipients) 1953 if err != nil { 1954 return nil, nil, nil, nil, err 1955 } 1956 implicitAdminBoxes[subteam.ID] = subteamBoxes 1957 } 1958 } 1959 1960 // if there are any removals happening, need to rotate the 1961 // team key, and recipients will be all the users in the team 1962 // after the removal. 1963 if memSet.HasRemoval() { 1964 if !skipKeyRotation { 1965 // key is rotating, so recipients needs to be all the remaining members 1966 // of the team after the removal (and including any new members in this 1967 // change) 1968 t.G().Log.CDebugf(ctx, "recipientBoxes: Team change request contains removal, rotating team key") 1969 boxes, perTeamKey, teamEKPayload, err := t.rotateBoxes(ctx, memSet) 1970 return boxes, implicitAdminBoxes, perTeamKey, teamEKPayload, err 1971 } 1972 1973 // If we don't rotate key, continue with the usual boxing. 1974 t.G().Log.CDebugf(ctx, "recipientBoxes: Skipping key rotation") 1975 } 1976 1977 // don't need keys for existing or restricted bot members, so remove them from the set 1978 memSet.removeExistingMembers(ctx, t) 1979 t.G().Log.CDebugf(ctx, "team change request: %d new members", len(memSet.recipients)) 1980 if len(memSet.recipients) == 0 { 1981 return nil, implicitAdminBoxes, nil, nil, nil 1982 } 1983 1984 boxes, err := t.keyManager.SharedSecretBoxes(t.MetaContext(ctx), deviceEncryptionKey, memSet.recipients) 1985 if err != nil { 1986 return nil, nil, nil, nil, err 1987 } 1988 // No SCPerTeamKey section or teamEKPayload when the key isn't rotated 1989 return boxes, implicitAdminBoxes, nil, nil, err 1990 } 1991 1992 func (t *Team) rotateBoxes(ctx context.Context, memSet *memberSet) (*PerTeamSharedSecretBoxes, *SCPerTeamKey, *teamEKPayload, error) { 1993 // get device key 1994 deviceEncryptionKey, err := t.G().ActiveDevice.EncryptionKey() 1995 if err != nil { 1996 return nil, nil, nil, err 1997 } 1998 1999 // rotate the team key for all current members except restricted bots. 2000 existing, err := t.Members() 2001 if err != nil { 2002 return nil, nil, nil, err 2003 } 2004 if err := memSet.AddRemainingRecipients(ctx, t.G(), existing); err != nil { 2005 return nil, nil, nil, err 2006 } 2007 2008 // Without adding extra admins, get get the recipients for the new teamEK 2009 recipients := memSet.recipientUids() 2010 2011 if t.IsSubteam() { 2012 // rotate needs to be keyed for all admins above it 2013 allParentAdmins, err := t.G().GetTeamLoader().ImplicitAdmins(ctx, t.ID) 2014 if err != nil { 2015 return nil, nil, nil, err 2016 } 2017 _, err = memSet.loadGroup(ctx, t.G(), allParentAdmins, storeMemberKindRecipient, true) 2018 if err != nil { 2019 return nil, nil, nil, err 2020 } 2021 } 2022 2023 t.rotated = true 2024 2025 boxes, key, err := t.keyManager.RotateSharedSecretBoxes(t.MetaContext(ctx), deviceEncryptionKey, memSet.recipients) 2026 if err != nil { 2027 return nil, nil, nil, err 2028 } 2029 2030 // Once we have the new PTK, let's make the new teamEK 2031 teamEKPayload, err := t.teamEKPayload(ctx, recipients) 2032 return boxes, key, teamEKPayload, err 2033 } 2034 2035 type teamEKPayload struct { 2036 sig string 2037 boxes *[]keybase1.TeamEkBoxMetadata 2038 metadata keybase1.TeamEkMetadata 2039 box *keybase1.TeamEkBoxed 2040 } 2041 2042 func (t *Team) teamEKPayload(ctx context.Context, recipients []keybase1.UID) (*teamEKPayload, error) { 2043 ekLib := t.G().GetEKLib() 2044 if ekLib == nil || len(recipients) == 0 { 2045 return nil, nil 2046 } 2047 2048 sigKey, err := t.SigningKey(ctx) 2049 if err != nil { 2050 return nil, err 2051 } 2052 mctx := libkb.NewMetaContext(ctx, t.G()) 2053 sig, boxes, metadata, box, err := ekLib.PrepareNewTeamEK(mctx, t.ID, sigKey, recipients) 2054 if err != nil { 2055 return nil, err 2056 } 2057 2058 return &teamEKPayload{ 2059 sig: sig, 2060 boxes: boxes, 2061 metadata: metadata, 2062 box: box, 2063 }, nil 2064 } 2065 2066 func (t *Team) storeTeamEKPayload(ctx context.Context, teamEKPayload *teamEKPayload) { 2067 // Add the new teamEK box to local storage, if it was created above. 2068 if teamEKPayload != nil && teamEKPayload.box != nil { 2069 mctx := libkb.NewMetaContext(ctx, t.G()) 2070 boxed := keybase1.NewTeamEphemeralKeyBoxedWithTeam(*teamEKPayload.box) 2071 if err := t.G().GetTeamEKBoxStorage().Put(mctx, t.ID, teamEKPayload.metadata.Generation, boxed); err != nil { 2072 t.G().Log.CErrorf(ctx, "error while saving teamEK box: %s", err) 2073 } 2074 } 2075 } 2076 2077 // createTeambotKeys generates teambotKeys and teambotEKs for the given bot 2078 // member list. Runs in the background on member addition or team rotation. 2079 func createTeambotKeys(g *libkb.GlobalContext, teamID keybase1.TeamID, bots []keybase1.UID) { 2080 mctx := libkb.NewMetaContextBackground(g) 2081 go func() { 2082 var err error 2083 defer mctx.Trace(fmt.Sprintf("createTeambotKeys: %d bot members", len(bots)), &err)() 2084 if len(bots) == 0 { 2085 return 2086 } 2087 2088 // Load the team in case we need to grab the latest PTK generation after a rotation. 2089 team, err := Load(mctx.Ctx(), g, keybase1.LoadTeamArg{ 2090 ID: teamID, 2091 }) 2092 if err != nil { 2093 return 2094 } 2095 2096 ekLib := mctx.G().GetEKLib() 2097 keyer := mctx.G().GetTeambotMemberKeyer() 2098 makeChatKey, makeKVStoreKey := true, true 2099 chatKey, err := team.ChatKey(mctx.Ctx()) 2100 if err != nil { 2101 mctx.Debug("unable to get teamApplication key %v, aborting TeambotKey appkey creation", err) 2102 makeChatKey = false 2103 } 2104 kvStoreKey, err := team.ApplicationKey(mctx.Ctx(), keybase1.TeamApplication_KVSTORE) 2105 if err != nil { 2106 mctx.Debug("unable to get teamApplication key %v, aborting TeambotKey creation", err) 2107 makeKVStoreKey = false 2108 } 2109 2110 for _, uid := range bots { 2111 guid := gregor1.UID(uid.ToBytes()) 2112 if ekLib != nil { 2113 if teambotEK, created, err := ekLib.GetOrCreateLatestTeambotEK(mctx, teamID, guid); err != nil { 2114 mctx.Debug("unable to GetOrCreateLatestTeambotEK for %v, %v", guid, err) 2115 } else { 2116 mctx.Debug("published TeambotEK generation %d for %v, newly created: %v", teambotEK.Generation(), uid, created) 2117 } 2118 } 2119 if keyer != nil { 2120 if makeChatKey { 2121 if teambotKey, created, err := keyer.GetOrCreateTeambotKey(mctx, teamID, guid, chatKey); err != nil { 2122 mctx.Debug("unable to GetOrCreateTeambotKey application %v, uid: %v, %v", 2123 keybase1.TeamApplication_CHAT, guid, err) 2124 } else { 2125 mctx.Debug("published TeambotKey app: %v generation %d for %v, newly created: %v", 2126 keybase1.TeamApplication_CHAT, teambotKey.Generation(), uid, created) 2127 } 2128 } 2129 if makeKVStoreKey { 2130 if teambotKey, created, err := keyer.GetOrCreateTeambotKey(mctx, teamID, guid, kvStoreKey); err != nil { 2131 mctx.Debug("unable to GetOrCreateTeambotKey application %v, uid: %v, %v", 2132 keybase1.TeamApplication_KVSTORE, guid, err) 2133 } else { 2134 mctx.Debug("published TeambotKey app: %v generation %d for %v, newly created: %v", 2135 keybase1.TeamApplication_KVSTORE, teambotKey.Generation(), uid, created) 2136 } 2137 } 2138 } 2139 } 2140 }() 2141 } 2142 2143 type sigPayloadArgs struct { 2144 secretBoxes *PerTeamSharedSecretBoxes 2145 implicitAdminBoxes map[keybase1.TeamID]*PerTeamSharedSecretBoxes 2146 lease *libkb.Lease 2147 prePayload libkb.JSONPayload 2148 legacyTLFUpgrade *keybase1.TeamGetLegacyTLFUpgrade 2149 teamEKBoxes *[]keybase1.TeamEkBoxMetadata 2150 teamEKPayload *teamEKPayload 2151 ratchetBlindingKeys hidden.EncodedRatchetBlindingKeySet 2152 } 2153 2154 func (t *Team) sigPayload(sigMulti []libkb.SigMultiItem, args sigPayloadArgs) libkb.JSONPayload { 2155 payload := libkb.JSONPayload{} 2156 // copy the prepayload so we don't mutate it 2157 for k, v := range args.prePayload { 2158 payload[k] = v 2159 } 2160 payload["sigs"] = sigMulti 2161 if args.secretBoxes != nil { 2162 payload["per_team_key"] = args.secretBoxes 2163 } 2164 if args.implicitAdminBoxes != nil { 2165 payload["implicit_team_keys"] = args.implicitAdminBoxes 2166 } 2167 if args.lease != nil { 2168 payload["downgrade_lease_id"] = args.lease.LeaseID 2169 } 2170 if args.legacyTLFUpgrade != nil { 2171 payload["legacy_tlf_upgrade"] = args.legacyTLFUpgrade 2172 } 2173 args.ratchetBlindingKeys.AddToJSONPayload(payload) 2174 if args.teamEKBoxes != nil && len(*args.teamEKBoxes) > 0 { 2175 payload["team_ek_rebox"] = libkb.JSONPayload{ 2176 "boxes": args.teamEKBoxes, 2177 "team_id": t.ID, 2178 } 2179 } else if args.teamEKPayload != nil { 2180 if args.teamEKPayload.boxes != nil && len(*args.teamEKPayload.boxes) > 0 { 2181 payload["team_ek"] = libkb.JSONPayload{ 2182 "sig": args.teamEKPayload.sig, 2183 "boxes": args.teamEKPayload.boxes, 2184 "team_id": t.ID, 2185 } 2186 } 2187 } 2188 2189 if t.G().VDL.DumpPayload() { 2190 pretty, err := json.MarshalIndent(payload, "", "\t") 2191 if err != nil { 2192 t.G().Log.Info("json marshal error: %s", err) 2193 } else { 2194 t.G().Log.Info("payload: %s", pretty) 2195 } 2196 } 2197 2198 return payload 2199 } 2200 2201 func (t *Team) postMulti(mctx libkb.MetaContext, payload libkb.JSONPayload) error { 2202 _, err := t.G().API.PostJSON(mctx, libkb.APIArg{ 2203 Endpoint: "sig/multi", 2204 SessionType: libkb.APISessionTypeREQUIRED, 2205 JSONPayload: payload, 2206 }) 2207 return err 2208 } 2209 2210 // ForceMerkleRootUpdate will call LookupTeam on MerkleClient to 2211 // update cached merkle root to include latest team sigs. Needed if 2212 // client wants to create a signature that refers to an adminship, 2213 // signature's merkle_root has to be more fresh than adminship's. 2214 func (t *Team) ForceMerkleRootUpdate(ctx context.Context) error { 2215 return ForceMerkleRootUpdateByTeamID(t.MetaContext(ctx), t.ID) 2216 } 2217 2218 func ForceMerkleRootUpdateByTeamID(mctx libkb.MetaContext, teamID keybase1.TeamID) error { 2219 _, err := mctx.G().GetMerkleClient().LookupTeam(mctx, teamID) 2220 return err 2221 } 2222 2223 // All admins, owners, and implicit admins of this team. 2224 func (t *Team) AllAdmins(ctx context.Context) ([]keybase1.UserVersion, error) { 2225 set := make(map[keybase1.UserVersion]bool) 2226 2227 owners, err := t.UsersWithRole(keybase1.TeamRole_OWNER) 2228 if err != nil { 2229 return nil, err 2230 } 2231 for _, m := range owners { 2232 set[m] = true 2233 } 2234 2235 admins, err := t.UsersWithRole(keybase1.TeamRole_ADMIN) 2236 if err != nil { 2237 return nil, err 2238 } 2239 for _, m := range admins { 2240 set[m] = true 2241 } 2242 2243 if t.IsSubteam() { 2244 imp, err := t.G().GetTeamLoader().ImplicitAdmins(ctx, t.ID) 2245 if err != nil { 2246 return nil, err 2247 } 2248 for _, m := range imp { 2249 set[m] = true 2250 } 2251 } 2252 2253 var all []keybase1.UserVersion 2254 for uv := range set { 2255 all = append(all, uv) 2256 } 2257 return all, nil 2258 } 2259 2260 // Restriction inherited from ListSubteams: 2261 // Only call this on a Team that has been loaded with NeedAdmin. 2262 // Otherwise, you might get incoherent answers due to links that 2263 // were stubbed over the life of the cached object. 2264 func (t *Team) loadAllTransitiveSubteams(ctx context.Context, forceRepoll bool) ([]*Team, error) { 2265 subteams := []*Team{} 2266 for _, idAndName := range t.chain().ListSubteams() { 2267 // Load each subteam... 2268 subteam, err := Load(ctx, t.G(), keybase1.LoadTeamArg{ 2269 ID: idAndName.Id, 2270 Public: t.IsPublic(), 2271 NeedAdmin: true, 2272 ForceRepoll: true, 2273 }) 2274 if err != nil { 2275 return nil, err 2276 } 2277 2278 // Force loading the key manager. 2279 // TODO: Should this be the default, so that we don't need to do it here? 2280 _, err = subteam.SharedSecret(ctx) 2281 if err != nil { 2282 return nil, err 2283 } 2284 2285 subteams = append(subteams, subteam) 2286 2287 // ...and then recursively load each subteam's children. 2288 recursiveSubteams, err := subteam.loadAllTransitiveSubteams(ctx, forceRepoll) 2289 if err != nil { 2290 return nil, err 2291 } 2292 subteams = append(subteams, recursiveSubteams...) 2293 } 2294 return subteams, nil 2295 } 2296 2297 func (t *Team) PostTeamSettings(ctx context.Context, settings keybase1.TeamSettings, rotate bool) error { 2298 if _, err := t.SharedSecret(ctx); err != nil { 2299 return err 2300 } 2301 2302 admin, err := t.getAdminPermission(ctx) 2303 if err != nil { 2304 return err 2305 } 2306 2307 mr, err := t.G().MerkleClient.FetchRootFromServer(t.MetaContext(ctx), libkb.TeamMerkleFreshnessForAdmin) 2308 if err != nil { 2309 return err 2310 } 2311 2312 scSettings, err := CreateTeamSettings(settings.Open, settings.JoinAs) 2313 if err != nil { 2314 return err 2315 } 2316 2317 ratchet, err := t.makeRatchet(ctx) 2318 if err != nil { 2319 return err 2320 } 2321 2322 section := SCTeamSection{ 2323 ID: SCTeamID(t.ID), 2324 Admin: admin, 2325 Settings: &scSettings, 2326 Implicit: t.IsImplicit(), 2327 Public: t.IsPublic(), 2328 Ratchets: ratchet.ToTeamSection(), 2329 } 2330 2331 payloadArgs := sigPayloadArgs{ 2332 ratchetBlindingKeys: ratchet.ToSigPayload(), 2333 } 2334 var maybeEKPayload *teamEKPayload 2335 var botMembers []keybase1.UID 2336 if rotate { 2337 // Create empty Members section. We are not changing memberships, but 2338 // it's needed for key rotation. 2339 memSet := newMemberSet() 2340 section.Members, err = memSet.Section() 2341 if err != nil { 2342 return err 2343 } 2344 secretBoxes, perTeamKeySection, teamEKPayload, err := t.rotateBoxes(ctx, memSet) 2345 if err != nil { 2346 return err 2347 } 2348 section.PerTeamKey = perTeamKeySection 2349 payloadArgs.secretBoxes = secretBoxes 2350 payloadArgs.teamEKPayload = teamEKPayload 2351 maybeEKPayload = teamEKPayload // for storeTeamEKPayload, after post succeeds 2352 botMembers = memSet.restrictedBotRecipientUids() 2353 } 2354 latestSeqno, err := t.postChangeItem(ctx, section, libkb.LinkTypeSettings, mr, payloadArgs) 2355 if err != nil { 2356 return err 2357 } 2358 2359 if rotate { 2360 err := t.notify(ctx, keybase1.TeamChangeSet{KeyRotated: true, Misc: true}, latestSeqno) 2361 if err != nil { 2362 return err 2363 } 2364 t.storeTeamEKPayload(ctx, maybeEKPayload) 2365 createTeambotKeys(t.G(), t.ID, botMembers) 2366 } else { 2367 err := t.notify(ctx, keybase1.TeamChangeSet{Misc: true}, latestSeqno) 2368 if err != nil { 2369 return err 2370 } 2371 } 2372 return nil 2373 } 2374 2375 func (t *Team) botSettingsSection(ctx context.Context, bots map[keybase1.UserVersion]keybase1.TeamBotSettings, 2376 ratchet *hidden.Ratchet, merkleRoot *libkb.MerkleRoot) (SCTeamSection, *hidden.Ratchet, error) { 2377 if _, err := t.SharedSecret(ctx); err != nil { 2378 return SCTeamSection{}, nil, err 2379 } 2380 2381 admin, err := t.getAdminPermission(ctx) 2382 if err != nil { 2383 return SCTeamSection{}, nil, err 2384 } 2385 2386 scBotSettings, err := CreateTeamBotSettings(bots) 2387 if err != nil { 2388 return SCTeamSection{}, nil, err 2389 } 2390 if ratchet == nil { 2391 ratchet, err = t.makeRatchet(ctx) 2392 if err != nil { 2393 return SCTeamSection{}, nil, err 2394 } 2395 } 2396 2397 section := SCTeamSection{ 2398 ID: SCTeamID(t.ID), 2399 Implicit: t.IsImplicit(), 2400 Public: t.IsPublic(), 2401 Admin: admin, 2402 BotSettings: &scBotSettings, 2403 Ratchets: ratchet.ToTeamSection(), 2404 } 2405 return section, ratchet, nil 2406 } 2407 2408 func (t *Team) PostTeamBotSettings(ctx context.Context, bots map[keybase1.UserVersion]keybase1.TeamBotSettings) error { 2409 2410 mr, err := t.G().MerkleClient.FetchRootFromServer(t.MetaContext(ctx), libkb.TeamMerkleFreshnessForAdmin) 2411 if err != nil { 2412 return err 2413 } 2414 2415 section, ratchet, err := t.botSettingsSection(ctx, bots, nil, mr) 2416 if err != nil { 2417 return err 2418 } 2419 2420 payloadArgs := sigPayloadArgs{ 2421 ratchetBlindingKeys: ratchet.ToSigPayload(), 2422 } 2423 _, err = t.postChangeItem(ctx, section, libkb.LinkTypeTeamBotSettings, mr, payloadArgs) 2424 return err 2425 } 2426 2427 func (t *Team) precheckLinksToPost(ctx context.Context, sigMultiItems []libkb.SigMultiItem) (err error) { 2428 uv, err := t.currentUserUV(ctx) 2429 if err != nil { 2430 return err 2431 } 2432 return precheckLinksToPost(ctx, t.G(), sigMultiItems, t.chain(), uv) 2433 } 2434 2435 // Try to run `post` (expected to post new team sigchain links). 2436 // Retry it several times if it fails due to being behind the latest team sigchain state or due to other retryable errors. 2437 // Passes the attempt number (initially 0) to `post`. 2438 func RetryIfPossible(ctx context.Context, g *libkb.GlobalContext, post func(ctx context.Context, attempt int) error) (err error) { 2439 mctx := libkb.NewMetaContext(ctx, g) 2440 defer mctx.Trace("RetryIfPossible", &err)() 2441 const nRetries = 3 2442 for i := 0; i < nRetries; i++ { 2443 mctx.Debug("| RetryIfPossible(%v)", i) 2444 err = post(mctx.Ctx(), i) 2445 switch { 2446 case isSigOldSeqnoError(err): 2447 mctx.Debug("| retrying due to SigOldSeqnoError %d", i) 2448 case isStaleBoxError(err): 2449 mctx.Debug("| retrying due to StaleBoxError %d", i) 2450 case isTeamBadGenerationError(err): 2451 mctx.Debug("| retrying due to Bad Generation Error (%s) %d", err, i) 2452 case isSigBadTotalOrder(err): 2453 mctx.Debug("| retrying since update would violate total ordering for team %d", i) 2454 case isSigMissingRatchet(err): 2455 mctx.Debug("| retrying since the server wanted a ratchet and we didn't provide one %d", i) 2456 case isHiddenAppendPrecheckError(err): 2457 mctx.Debug("| retrying since we hit a hidden append precheck error") 2458 case libkb.IsEphemeralRetryableError(err): 2459 mctx.Debug("| retrying since we hit a retryable ephemeral error %v, attempt %d", err, i) 2460 default: 2461 return err 2462 } 2463 } 2464 mctx.Debug("| RetryIfPossible exhausted attempts") 2465 if err == nil { 2466 // Should never happen 2467 return fmt.Errorf("failed retryable team operation") 2468 } 2469 // Return the error from the final round 2470 return err 2471 } 2472 2473 func isHiddenAppendPrecheckError(err error) bool { 2474 perr, ok := err.(PrecheckAppendError) 2475 if !ok { 2476 return false 2477 } 2478 _, ok = perr.Inner.(hidden.LoaderError) 2479 return ok 2480 } 2481 2482 func isSigOldSeqnoError(err error) bool { 2483 return libkb.IsAppStatusCode(err, keybase1.StatusCode_SCSigOldSeqno) 2484 } 2485 2486 func isSigBadTotalOrder(err error) bool { 2487 return libkb.IsAppStatusCode(err, keybase1.StatusCode_SCSigBadTotalOrder) 2488 } 2489 2490 func isSigMissingRatchet(err error) bool { 2491 return libkb.IsAppStatusCode(err, keybase1.StatusCode_SCSigMissingRatchet) 2492 } 2493 2494 func isTeamBadGenerationError(err error) bool { 2495 return libkb.IsAppStatusCode(err, keybase1.StatusCode_SCTeamBadGeneration) 2496 } 2497 2498 func (t *Team) marshal(incoming interface{}) ([]byte, error) { 2499 var data []byte 2500 mh := codec.MsgpackHandle{WriteExt: true} 2501 enc := codec.NewEncoderBytes(&data, &mh) 2502 if err := enc.Encode(incoming); err != nil { 2503 return nil, err 2504 } 2505 return data, nil 2506 } 2507 2508 func (t *Team) boxKBFSCryptKeys(ctx context.Context, key keybase1.TeamApplicationKey, 2509 kbfsKeys []keybase1.CryptKey) (string, keybase1.TeamEncryptedKBFSKeysetHash, error) { 2510 2511 marshaledKeys, err := t.marshal(kbfsKeys) 2512 if err != nil { 2513 return "", "", err 2514 } 2515 2516 var nonce [libkb.NaclDHNonceSize]byte 2517 if _, err := rand.Read(nonce[:]); err != nil { 2518 return "", "", err 2519 } 2520 2521 var encKey [libkb.NaclSecretBoxKeySize]byte = key.Material() 2522 sealed := secretbox.Seal(nil, marshaledKeys, &nonce, &encKey) 2523 dat := keybase1.TeamEncryptedKBFSKeyset{ 2524 V: 1, 2525 N: nonce[:], 2526 E: sealed, 2527 } 2528 2529 marshaledSealedDat, err := t.marshal(dat) 2530 if err != nil { 2531 return "", "", err 2532 } 2533 2534 encStr := base64.StdEncoding.EncodeToString(marshaledSealedDat) 2535 sbytes := sha256.Sum256([]byte(encStr)) 2536 return encStr, keybase1.TeamEncryptedKBFSKeysetHashFromBytes(sbytes[:]), nil 2537 } 2538 2539 func (t *Team) AssociateWithTLFKeyset(ctx context.Context, tlfID keybase1.TLFID, 2540 cryptKeys []keybase1.CryptKey, appType keybase1.TeamApplication) (err error) { 2541 m := t.MetaContext(ctx) 2542 defer m.Trace("Team.AssociateWithTLFKeyset", &err)() 2543 2544 // If we get no crypt keys, just associate TLF ID and bail 2545 if len(cryptKeys) == 0 { 2546 m.Debug("AssociateWithTLFKeyset: no crypt keys given, aborting") 2547 return nil 2548 } 2549 2550 // Sort crypt keys by generation (just in case they aren't naturally) 2551 sort.Slice(cryptKeys, func(i, j int) bool { 2552 return cryptKeys[i].KeyGeneration < cryptKeys[j].KeyGeneration 2553 }) 2554 2555 latestKey, err := t.ApplicationKey(ctx, appType) 2556 if err != nil { 2557 return err 2558 } 2559 encStr, hash, err := t.boxKBFSCryptKeys(ctx, latestKey, cryptKeys) 2560 if err != nil { 2561 return err 2562 } 2563 2564 ratchet, err := t.makeRatchet(ctx) 2565 if err != nil { 2566 return err 2567 } 2568 2569 upgrade := SCTeamKBFSLegacyUpgrade{ 2570 AppType: appType, 2571 KeysetHash: hash, 2572 LegacyGeneration: cryptKeys[len(cryptKeys)-1].Generation(), 2573 TeamGeneration: latestKey.KeyGeneration, 2574 } 2575 teamSection := SCTeamSection{ 2576 ID: SCTeamID(t.ID), 2577 Implicit: t.IsImplicit(), 2578 Public: t.IsPublic(), 2579 KBFS: &SCTeamKBFS{ 2580 Keyset: &upgrade, 2581 }, 2582 Ratchets: ratchet.ToTeamSection(), 2583 } 2584 2585 mr, err := m.G().MerkleClient.FetchRootFromServer(m, libkb.TeamMerkleFreshnessForAdmin) 2586 if err != nil { 2587 return err 2588 } 2589 if mr == nil { 2590 return errors.New("No merkle root available for KBFS settings update") 2591 } 2592 2593 sigMultiItem, latestSeqno, err := t.sigTeamItem(ctx, teamSection, libkb.LinkTypeKBFSSettings, mr) 2594 if err != nil { 2595 return err 2596 } 2597 2598 payload := t.sigPayload([]libkb.SigMultiItem{sigMultiItem}, sigPayloadArgs{ 2599 legacyTLFUpgrade: &keybase1.TeamGetLegacyTLFUpgrade{ 2600 EncryptedKeyset: encStr, 2601 LegacyGeneration: cryptKeys[len(cryptKeys)-1].Generation(), 2602 TeamGeneration: latestKey.KeyGeneration, 2603 AppType: appType, 2604 }, 2605 ratchetBlindingKeys: ratchet.ToSigPayload(), 2606 }) 2607 2608 err = t.postMulti(m, payload) 2609 if err != nil { 2610 return err 2611 } 2612 2613 return t.HintLatestSeqno(m, latestSeqno) 2614 } 2615 2616 func (t *Team) AssociateWithTLFID(ctx context.Context, tlfID keybase1.TLFID) (err error) { 2617 m := t.MetaContext(ctx) 2618 defer m.Trace("Team.AssociateWithTLFID", &err)() 2619 2620 if tlfID.Eq(t.LatestKBFSTLFID()) { 2621 m.Debug("No updated needed, TLFID already set to %s", tlfID) 2622 return nil 2623 } 2624 2625 ratchet, err := t.makeRatchet(ctx) 2626 if err != nil { 2627 return err 2628 } 2629 2630 teamSection := SCTeamSection{ 2631 ID: SCTeamID(t.ID), 2632 Implicit: t.IsImplicit(), 2633 Public: t.IsPublic(), 2634 KBFS: &SCTeamKBFS{ 2635 TLF: &SCTeamKBFSTLF{ 2636 ID: tlfID, 2637 }, 2638 }, 2639 Ratchets: ratchet.ToTeamSection(), 2640 } 2641 2642 mr, err := m.G().MerkleClient.FetchRootFromServer(m, libkb.TeamMerkleFreshnessForAdmin) 2643 if err != nil { 2644 return err 2645 } 2646 if mr == nil { 2647 return errors.New("No merkle root available for KBFS settings update") 2648 } 2649 2650 sigMultiItem, latestSeqno, err := t.sigTeamItem(ctx, teamSection, libkb.LinkTypeKBFSSettings, mr) 2651 if err != nil { 2652 return err 2653 } 2654 2655 sigPayloadArgs := sigPayloadArgs{ 2656 ratchetBlindingKeys: ratchet.ToSigPayload(), 2657 } 2658 payload := t.sigPayload([]libkb.SigMultiItem{sigMultiItem}, sigPayloadArgs) 2659 err = t.postMulti(libkb.NewMetaContext(ctx, t.G()), payload) 2660 if err != nil { 2661 return err 2662 } 2663 return t.HintLatestSeqno(m, latestSeqno) 2664 } 2665 2666 func (t *Team) notifyNoChainChange(ctx context.Context, changes keybase1.TeamChangeSet) error { 2667 return t.notify(ctx, changes, t.CurrentSeqno()) 2668 } 2669 2670 // Send notifyrouter messages. 2671 // Modifies `changes` 2672 // Update to the latest seqno that we're passing though, don't make any assumptions about number of sigs. 2673 // Note that we're probably going to be getting this same notification a second time, since it will 2674 // bounce off a gregor and back to us. But they are idempotent, so it should be fine to be double-notified. 2675 func (t *Team) notify(ctx context.Context, changes keybase1.TeamChangeSet, latestSeqno keybase1.Seqno) error { 2676 changes.KeyRotated = changes.KeyRotated || t.rotated 2677 m := libkb.NewMetaContext(ctx, t.G()) 2678 var err error 2679 if latestSeqno > 0 { 2680 err = HintLatestSeqno(m, t.ID, latestSeqno) 2681 } 2682 t.G().NotifyRouter.HandleTeamChangedByBothKeys(ctx, t.ID, t.Name().String(), latestSeqno, t.IsImplicit(), 2683 changes, keybase1.Seqno(0) /* hiddenSeqno */, keybase1.Seqno(0) /* offchainSeqno */, keybase1.TeamChangedSource_LOCAL) 2684 return err 2685 } 2686 2687 func (t *Team) HintLatestSeqno(m libkb.MetaContext, n keybase1.Seqno) error { 2688 return HintLatestSeqno(m, t.ID, n) 2689 } 2690 2691 func HintLatestSeqno(m libkb.MetaContext, id keybase1.TeamID, n keybase1.Seqno) error { 2692 err := m.G().GetTeamLoader().HintLatestSeqno(m.Ctx(), id, n) 2693 if err != nil { 2694 m.Warning("error in TeamLoader#HintLatestSeqno: %v", err) 2695 } 2696 e2 := m.G().GetFastTeamLoader().HintLatestSeqno(m, id, n) 2697 if e2 != nil { 2698 m.Warning("error in FastTeamLoader#HintLatestSeqno: %v", err) 2699 } 2700 if err != nil { 2701 return err 2702 } 2703 return e2 2704 } 2705 2706 func HintLatestHiddenSeqno(m libkb.MetaContext, id keybase1.TeamID, n keybase1.Seqno) error { 2707 err := m.G().GetHiddenTeamChainManager().HintLatestSeqno(m, id, n) 2708 if err != nil { 2709 m.Warning("error in HintLatestHiddenSeqno: %v", err) 2710 } 2711 return err 2712 } 2713 2714 func (t *Team) refreshUIDMapper(ctx context.Context, g *libkb.GlobalContext) { 2715 for uv := range t.chain().inner.UserLog { 2716 _, err := g.UIDMapper.InformOfEldestSeqno(ctx, g, uv) 2717 if err != nil { 2718 g.Log.CDebugf(ctx, "Error informing eldest seqno: %+v", err.Error()) 2719 } 2720 } 2721 for _, inviteMD := range t.chain().ActiveInvites() { 2722 invite := inviteMD.Invite 2723 invtype, err := invite.Type.C() 2724 if err != nil { 2725 g.Log.CDebugf(ctx, "Error in invite %s: %s", invite.Id, err.Error()) 2726 continue 2727 } 2728 if invtype == keybase1.TeamInviteCategory_KEYBASE { 2729 uv, err := invite.KeybaseUserVersion() 2730 if err != nil { 2731 g.Log.CDebugf(ctx, "Error in parsing invite %s: %s", invite.Id, err.Error()) 2732 } 2733 _, err = g.UIDMapper.InformOfEldestSeqno(ctx, g, uv) 2734 if err != nil { 2735 g.Log.CDebugf(ctx, "Error informing eldest seqno: %+v", err.Error()) 2736 } 2737 } 2738 } 2739 } 2740 2741 func UpgradeTLFIDToImpteam(ctx context.Context, g *libkb.GlobalContext, tlfName string, tlfID keybase1.TLFID, 2742 public bool, appType keybase1.TeamApplication, cryptKeys []keybase1.CryptKey) (err error) { 2743 defer g.CTrace(ctx, fmt.Sprintf("UpgradeTLFIDToImpteam(%s)", tlfID), &err)() 2744 2745 var team *Team 2746 if team, _, _, err = LookupOrCreateImplicitTeam(ctx, g, tlfName, public); err != nil { 2747 return err 2748 } 2749 2750 // Associate the imp team with the TLF ID 2751 if team.LatestKBFSTLFID().IsNil() { 2752 if err = team.AssociateWithTLFID(ctx, tlfID); err != nil { 2753 return err 2754 } 2755 } else { 2756 if team.LatestKBFSTLFID().String() != tlfID.String() { 2757 return fmt.Errorf("implicit team already associated with different TLF ID: teamID: %s tlfID: %s", 2758 team.ID, tlfID) 2759 } 2760 } 2761 2762 // Reload the team 2763 if team, err = Load(ctx, g, keybase1.LoadTeamArg{ 2764 ID: team.ID, 2765 Public: public, 2766 ForceRepoll: true, 2767 }); err != nil { 2768 return err 2769 } 2770 2771 // Post the crypt keys 2772 return team.AssociateWithTLFKeyset(ctx, tlfID, cryptKeys, appType) 2773 } 2774 2775 func TeamInviteTypeFromString(mctx libkb.MetaContext, inviteTypeStr string) (keybase1.TeamInviteType, error) { 2776 switch inviteTypeStr { 2777 case "keybase": 2778 return keybase1.NewTeamInviteTypeDefault(keybase1.TeamInviteCategory_KEYBASE), nil 2779 case "email": 2780 return keybase1.NewTeamInviteTypeDefault(keybase1.TeamInviteCategory_EMAIL), nil 2781 case "seitan_invite_token": 2782 return keybase1.NewTeamInviteTypeDefault(keybase1.TeamInviteCategory_SEITAN), nil 2783 case "phone": 2784 return keybase1.NewTeamInviteTypeDefault(keybase1.TeamInviteCategory_PHONE), nil 2785 case "invitelink": 2786 return keybase1.NewTeamInviteTypeDefault(keybase1.TeamInviteCategory_INVITELINK), nil 2787 case "twitter", "github", "facebook", "reddit", "hackernews", "pgp", "http", "https", "dns": 2788 return keybase1.NewTeamInviteTypeWithSbs(keybase1.TeamInviteSocialNetwork(inviteTypeStr)), nil 2789 default: 2790 if mctx.G().GetProofServices().GetServiceType(mctx.Ctx(), inviteTypeStr) != nil { 2791 return keybase1.NewTeamInviteTypeWithSbs(keybase1.TeamInviteSocialNetwork(inviteTypeStr)), nil 2792 } 2793 2794 isDev := mctx.G().Env.GetRunMode() == libkb.DevelRunMode 2795 if isDev && inviteTypeStr == "rooter" { 2796 return keybase1.NewTeamInviteTypeWithSbs(keybase1.TeamInviteSocialNetwork(inviteTypeStr)), nil 2797 } 2798 // Don't want to break existing clients if we see an unknown invite type. 2799 return keybase1.NewTeamInviteTypeWithUnknown(inviteTypeStr), nil 2800 } 2801 } 2802 2803 func FreezeTeam(mctx libkb.MetaContext, teamID keybase1.TeamID) error { 2804 err3 := mctx.G().GetHiddenTeamChainManager().Freeze(mctx, teamID) 2805 if err3 != nil { 2806 mctx.Debug("error freezing in hidden team chain manager: %v", err3) 2807 } 2808 err1 := mctx.G().GetTeamLoader().Freeze(mctx.Ctx(), teamID) 2809 if err1 != nil { 2810 mctx.Debug("error freezing in team cache: %v", err1) 2811 } 2812 err2 := mctx.G().GetFastTeamLoader().Freeze(mctx, teamID) 2813 if err2 != nil { 2814 mctx.Debug("error freezing in fast team cache: %v", err2) 2815 } 2816 return libkb.CombineErrors(err1, err2, err3) 2817 } 2818 2819 func TombstoneTeam(mctx libkb.MetaContext, teamID keybase1.TeamID) error { 2820 err3 := mctx.G().GetHiddenTeamChainManager().Tombstone(mctx, teamID) 2821 if err3 != nil { 2822 mctx.Debug("error tombstoning in hidden team chain manager: %v", err3) 2823 if _, ok := err3.(hidden.TombstonedError); ok { 2824 err3 = nil 2825 } 2826 } 2827 err1 := mctx.G().GetTeamLoader().Tombstone(mctx.Ctx(), teamID) 2828 if err1 != nil { 2829 mctx.Debug("error tombstoning in team cache: %v", err1) 2830 if _, ok := err1.(TeamTombstonedError); ok { 2831 err1 = nil 2832 } 2833 } 2834 err2 := mctx.G().GetFastTeamLoader().Tombstone(mctx, teamID) 2835 if err2 != nil { 2836 mctx.Debug("error tombstoning in fast team cache: %v", err2) 2837 if _, ok := err2.(TeamTombstonedError); ok { 2838 err2 = nil 2839 } 2840 } 2841 return libkb.CombineErrors(err1, err2, err3) 2842 } 2843 2844 type TeamShim struct { 2845 Data *keybase1.TeamData 2846 Hidden *keybase1.HiddenTeamChain 2847 } 2848 2849 func (t *TeamShim) MainChain() *keybase1.TeamData { return t.Data } 2850 func (t *TeamShim) HiddenChain() *keybase1.HiddenTeamChain { return t.Hidden } 2851 2852 var _ Teamer = (*TeamShim)(nil) 2853 2854 func KeySummary(t Teamer) string { 2855 if t == nil { 2856 return "Ø" 2857 } 2858 return fmt.Sprintf("{main:%s, hidden:%s}", t.MainChain().KeySummary(), t.HiddenChain().KeySummary()) 2859 } 2860 2861 type TeamInfo struct { 2862 libkb.AppStatusEmbed 2863 Name string 2864 InTeam bool `json:"in_team"` 2865 Open bool 2866 Description string 2867 PublicAdmins []string `json:"public_admins"` 2868 NumMembers int `json:"num_members"` 2869 PublicMembers []struct { 2870 Role keybase1.TeamRole 2871 UID keybase1.UID 2872 Username string 2873 FullName string `json:"full_name"` 2874 } `json:"public_members"` 2875 } 2876 2877 func GetUntrustedTeamInfo(mctx libkb.MetaContext, name keybase1.TeamName) (info keybase1.UntrustedTeamInfo, err error) { 2878 arg := libkb.APIArg{ 2879 Endpoint: "team/mentiondesc", 2880 SessionType: libkb.APISessionTypeREQUIRED, 2881 Args: libkb.HTTPArgs{ 2882 "name": libkb.S{Val: name.String()}, 2883 "include_all_members": libkb.B{Val: true}, // refers to members who showcased the team on their profile only 2884 }, 2885 } 2886 2887 var resp TeamInfo 2888 if err = mctx.G().API.GetDecode(mctx, arg, &resp); err != nil { 2889 mctx.Debug("GetUntrustedTeamInfo: failed to get team info: %s", err) 2890 } 2891 if err != nil { 2892 return info, err 2893 } 2894 2895 teamName, err := keybase1.TeamNameFromString(resp.Name) 2896 if err != nil { 2897 return info, err 2898 } 2899 2900 teamInfo := keybase1.UntrustedTeamInfo{ 2901 Name: teamName, 2902 Description: resp.Description, 2903 InTeam: resp.InTeam, 2904 NumMembers: resp.NumMembers, 2905 Open: resp.Open, 2906 PublicAdmins: resp.PublicAdmins, 2907 } 2908 2909 for _, mem := range resp.PublicMembers { 2910 teamInfo.PublicMembers = append(teamInfo.PublicMembers, keybase1.TeamMemberRole{ 2911 Uid: mem.UID, 2912 FullName: keybase1.FullName(mem.FullName), 2913 Role: mem.Role, 2914 Username: mem.Username, 2915 }) 2916 } 2917 2918 return teamInfo, nil 2919 } 2920 2921 func GetUntrustedTeamExists(mctx libkb.MetaContext, name keybase1.TeamName) (teamExistsResult keybase1.UntrustedTeamExistsResult, err error) { 2922 type resType struct { 2923 libkb.AppStatusEmbed 2924 Exists bool `json:"exists"` 2925 Sc keybase1.StatusCode `json:"sc"` 2926 } 2927 var res resType 2928 err = mctx.G().API.GetDecode(mctx, libkb.APIArg{ 2929 Endpoint: "team/exists", 2930 SessionType: libkb.APISessionTypeREQUIRED, 2931 Args: libkb.HTTPArgs{ 2932 "teamName": libkb.S{Val: name.String()}, 2933 }, 2934 }, &res) 2935 if err != nil { 2936 mctx.Debug("GetUntrustedTeamInfo: failed to get team info: %s", err) 2937 return teamExistsResult, err 2938 } 2939 2940 return keybase1.UntrustedTeamExistsResult{ 2941 Exists: res.Exists, 2942 Status: res.Sc, 2943 }, nil 2944 }