github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libkbfs/root_metadata_test.go (about) 1 // Copyright 2016 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package libkbfs 6 7 import ( 8 "bytes" 9 "fmt" 10 "reflect" 11 "runtime" 12 "strings" 13 "testing" 14 "time" 15 16 "github.com/keybase/client/go/kbfs/data" 17 "github.com/keybase/client/go/kbfs/kbfsblock" 18 "github.com/keybase/client/go/kbfs/kbfscodec" 19 "github.com/keybase/client/go/kbfs/kbfscrypto" 20 "github.com/keybase/client/go/kbfs/kbfsmd" 21 "github.com/keybase/client/go/kbfs/tlf" 22 "github.com/keybase/client/go/kbfs/tlfhandle" 23 kbname "github.com/keybase/client/go/kbun" 24 "github.com/keybase/client/go/protocol/keybase1" 25 "github.com/keybase/go-codec/codec" 26 "github.com/pkg/errors" 27 "github.com/stretchr/testify/require" 28 "golang.org/x/net/context" 29 ) 30 31 var testMetadataVers = []kbfsmd.MetadataVer{ 32 kbfsmd.InitialExtraMetadataVer, kbfsmd.ImplicitTeamsVer, 33 } 34 35 // runTestOverMetadataVers runs the given test function over all 36 // metadata versions to test. The test is assumed to be parallelizable 37 // with other instances of itself. Example use: 38 // 39 // func TestFoo(t *testing.T) { 40 // runTestOverMetadataVers(t, testFoo) 41 // } 42 // 43 // func testFoo(t *testing.T, ver MetadataVer) { 44 // ... 45 // brmd, err := MakeInitialRootMetadata(ver, ...) 46 // ... 47 // } 48 func runTestOverMetadataVers( 49 t *testing.T, f func(t *testing.T, ver kbfsmd.MetadataVer)) { 50 for _, ver := range testMetadataVers { 51 ver := ver // capture range variable. 52 t.Run(ver.String(), func(t *testing.T) { 53 f(t, ver) 54 }) 55 } 56 } 57 58 // runTestsOverMetadataVers runs the given list of test functions over 59 // all metadata versions to test. prefix should be the common prefix 60 // for all the test function names, and the names of the subtest will 61 // be taken to be the strings after that prefix. Example use: 62 // 63 // func TestFoo(t *testing.T) { 64 // tests := []func(*testing.T, kbfsmd.MetadataVer){ 65 // testFooBar1, 66 // testFooBar2, 67 // testFooBar3, 68 // ... 69 // } 70 // runTestsOverMetadataVers(t, "testFoo", tests) 71 // } 72 func runTestsOverMetadataVers(t *testing.T, prefix string, 73 fs []func(t *testing.T, ver kbfsmd.MetadataVer)) { 74 for _, f := range fs { 75 f := f // capture range variable. 76 name := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name() 77 i := strings.LastIndex(name, prefix) 78 if i >= 0 { 79 i += len(prefix) 80 } else { 81 i = 0 82 } 83 name = name[i:] 84 t.Run(name, func(t *testing.T) { 85 runTestOverMetadataVers(t, f) 86 }) 87 } 88 } 89 90 // runBenchmarkOverMetadataVers runs the given benchmark function over 91 // all metadata versions to test. Example use: 92 // 93 // func BenchmarkFoo(b *testing.B) { 94 // runBenchmarkOverMetadataVers(b, testFoo) 95 // } 96 // 97 // func benchmarkFoo(b *testing.B, ver kbfsmd.MetadataVer) { 98 // ... 99 // brmd, err := MakeInitialRootMetadata(ver, ...) 100 // ... 101 // } 102 func runBenchmarkOverMetadataVers( 103 b *testing.B, f func(b *testing.B, ver kbfsmd.MetadataVer)) { 104 for _, ver := range testMetadataVers { 105 ver := ver // capture range variable. 106 b.Run(ver.String(), func(b *testing.B) { 107 f(b, ver) 108 }) 109 } 110 } 111 112 // TODO: Add way to test with all possible (ver, maxVer) combos, 113 // e.g. for upconversion tests. 114 115 type privateMetadataFuture struct { 116 PrivateMetadata 117 kbfscodec.Extra 118 } 119 120 func (pmf privateMetadataFuture) toCurrent() PrivateMetadata { 121 pm := pmf.PrivateMetadata 122 pm.Dir = pmf.Dir 123 pm.Changes.Ops = make(opsList, len(pmf.Changes.Ops)) 124 for i, opFuture := range pmf.Changes.Ops { 125 currentOp := opFuture.(kbfscodec.FutureStruct).ToCurrentStruct() 126 // A generic version of "v := currentOp; ...Ops[i] = &v". 127 v := reflect.New(reflect.TypeOf(currentOp)) 128 v.Elem().Set(reflect.ValueOf(currentOp)) 129 pm.Changes.Ops[i] = v.Interface().(op) 130 } 131 return pm 132 } 133 134 func (pmf privateMetadataFuture) ToCurrentStruct() kbfscodec.CurrentStruct { 135 return pmf.toCurrent() 136 } 137 138 func makeFakePrivateMetadataFuture(t *testing.T) privateMetadataFuture { 139 createOp := makeFakeCreateOpFuture(t) 140 rmOp := makeFakeRmOpFuture(t) 141 renameOp := makeFakeRenameOpFuture(t) 142 syncOp := makeFakeSyncOpFuture(t) 143 setAttrOp := makeFakeSetAttrOpFuture(t) 144 resolutionOp := makeFakeResolutionOpFuture(t) 145 rekeyOp := makeFakeRekeyOpFuture(t) 146 gcOp := makeFakeGcOpFuture(t) 147 148 pmf := privateMetadataFuture{ 149 PrivateMetadata{ 150 data.DirEntry{}, 151 kbfscrypto.MakeTLFPrivateKey([32]byte{0xb}), 152 BlockChanges{ 153 makeFakeBlockInfo(t), 154 opsList{ 155 &createOp, 156 &rmOp, 157 &renameOp, 158 &syncOp, 159 &setAttrOp, 160 &resolutionOp, 161 &rekeyOp, 162 &gcOp, 163 }, 164 0, 165 }, 166 0, 167 codec.UnknownFieldSetHandler{}, 168 BlockChanges{}, 169 }, 170 kbfscodec.MakeExtraOrBust("PrivateMetadata", t), 171 } 172 return pmf 173 } 174 175 func TestPrivateMetadataUnknownFields(t *testing.T) { 176 testStructUnknownFields(t, makeFakePrivateMetadataFuture(t)) 177 } 178 179 // makeFakeTlfHandle should only be used in this file. 180 func makeFakeTlfHandle( 181 t *testing.T, x uint32, ty tlf.Type, 182 unresolvedWriters, unresolvedReaders []keybase1.SocialAssertion) *tlfhandle.Handle { 183 id := keybase1.MakeTestUID(x).AsUserOrTeam() 184 return tlfhandle.NewHandle( 185 ty, map[keybase1.UserOrTeamID]kbname.NormalizedUsername{ 186 id: "test_user", 187 }, unresolvedWriters, unresolvedReaders, "", tlf.NullID) 188 } 189 190 // Test that GetTlfHandle() and MakeBareTlfHandle() work properly for 191 // public TLFs. 192 func testRootMetadataGetTlfHandlePublic(t *testing.T, ver kbfsmd.MetadataVer) { 193 uw := []keybase1.SocialAssertion{ 194 { 195 User: "user2", 196 Service: "service3", 197 }, 198 { 199 User: "user1", 200 Service: "service1", 201 }, 202 } 203 h := makeFakeTlfHandle(t, 14, tlf.Public, uw, nil) 204 tlfID := tlf.FakeID(0, tlf.Public) 205 rmd, err := makeInitialRootMetadata(ver, tlfID, h) 206 require.NoError(t, err) 207 208 dirHandle := rmd.GetTlfHandle() 209 require.Equal(t, h, dirHandle) 210 211 rmd.tlfHandle = nil 212 bh, err := rmd.MakeBareTlfHandle() 213 require.NoError(t, err) 214 require.Equal(t, h.ToBareHandleOrBust(), bh) 215 } 216 217 // Test that GetTlfHandle() and MakeBareTlfHandle() work properly for 218 // non-public TLFs. 219 func testRootMetadataGetTlfHandlePrivate(t *testing.T, ver kbfsmd.MetadataVer) { 220 uw := []keybase1.SocialAssertion{ 221 { 222 User: "user2", 223 Service: "service3", 224 }, 225 { 226 User: "user1", 227 Service: "service1", 228 }, 229 } 230 ur := []keybase1.SocialAssertion{ 231 { 232 User: "user5", 233 Service: "service3", 234 }, 235 { 236 User: "user1", 237 Service: "service2", 238 }, 239 } 240 h := makeFakeTlfHandle(t, 14, tlf.Private, uw, ur) 241 tlfID := tlf.FakeID(0, tlf.Private) 242 rmd, err := makeInitialRootMetadata(ver, tlfID, h) 243 require.NoError(t, err) 244 245 rmd.fakeInitialRekey() 246 247 dirHandle := rmd.GetTlfHandle() 248 require.Equal(t, h, dirHandle) 249 250 rmd.tlfHandle = nil 251 bh, err := rmd.MakeBareTlfHandle() 252 require.NoError(t, err) 253 require.Equal(t, h.ToBareHandleOrBust(), bh) 254 } 255 256 // Test that key generations work as expected for private TLFs. 257 func testRootMetadataLatestKeyGenerationPrivate(t *testing.T, ver kbfsmd.MetadataVer) { 258 tlfID := tlf.FakeID(0, tlf.Private) 259 h := makeFakeTlfHandle(t, 14, tlf.Private, nil, nil) 260 rmd, err := makeInitialRootMetadata(ver, tlfID, h) 261 require.NoError(t, err) 262 263 if rmd.LatestKeyGeneration() != 0 { 264 t.Errorf("Expected key generation to be invalid (0)") 265 } 266 rmd.fakeInitialRekey() 267 if rmd.LatestKeyGeneration() != kbfsmd.FirstValidKeyGen { 268 t.Errorf("Expected key generation to be valid(%d)", kbfsmd.FirstValidKeyGen) 269 } 270 } 271 272 // Test that key generations work as expected for public TLFs. 273 func testRootMetadataLatestKeyGenerationPublic(t *testing.T, ver kbfsmd.MetadataVer) { 274 tlfID := tlf.FakeID(0, tlf.Public) 275 h := makeFakeTlfHandle(t, 14, tlf.Public, nil, nil) 276 rmd, err := makeInitialRootMetadata(ver, tlfID, h) 277 require.NoError(t, err) 278 279 if rmd.LatestKeyGeneration() != kbfsmd.PublicKeyGen { 280 t.Errorf("Expected key generation to be public (%d)", kbfsmd.PublicKeyGen) 281 } 282 } 283 284 func testMakeRekeyReadError(t *testing.T, ver kbfsmd.MetadataVer) { 285 ctx := context.Background() 286 config := MakeTestConfigOrBust(t, "alice", "bob") 287 config.SetMetadataVersion(ver) 288 defer CheckConfigAndShutdown(ctx, t, config) 289 290 tlfID := tlf.FakeID(1, tlf.Private) 291 h := parseTlfHandleOrBust(t, config, "alice", tlf.Private, tlfID) 292 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), tlfID, h) 293 require.NoError(t, err) 294 295 rmd.fakeInitialRekey() 296 297 u, id, err := config.KBPKI().Resolve( 298 ctx, "bob", keybase1.OfflineAvailability_NONE) 299 require.NoError(t, err) 300 uid, err := id.AsUser() 301 require.NoError(t, err) 302 303 dummyErr := errors.New("dummy") 304 err = makeRekeyReadErrorHelper(dummyErr, rmd.ReadOnly(), h, uid, u) 305 require.Equal( 306 t, tlfhandle.NewReadAccessError(h, u, "/keybase/private/alice"), err) 307 308 err = makeRekeyReadErrorHelper(dummyErr, 309 rmd.ReadOnly(), h, h.FirstResolvedWriter().AsUserOrBust(), "alice") 310 require.Equal(t, NeedSelfRekeyError{"alice", dummyErr}, err) 311 } 312 313 func testMakeRekeyReadErrorResolvedHandle(t *testing.T, ver kbfsmd.MetadataVer) { 314 ctx := context.Background() 315 config := MakeTestConfigOrBust(t, "alice", "bob") 316 defer CheckConfigAndShutdown(ctx, t, config) 317 318 tlfID := tlf.FakeID(1, tlf.Private) 319 h, err := tlfhandle.ParseHandle( 320 ctx, config.KBPKI(), config.MDOps(), nil, 321 "alice,bob@twitter", tlf.Private) 322 require.NoError(t, err) 323 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), tlfID, h) 324 require.NoError(t, err) 325 326 rmd.fakeInitialRekey() 327 328 u, id, err := config.KBPKI().Resolve( 329 ctx, "bob", keybase1.OfflineAvailability_NONE) 330 require.NoError(t, err) 331 uid, err := id.AsUser() 332 require.NoError(t, err) 333 334 err = makeRekeyReadErrorHelper(errors.New("dummy"), 335 rmd.ReadOnly(), h, uid, u) 336 require.Equal(t, tlfhandle.NewReadAccessError( 337 h, u, "/keybase/private/alice,bob@twitter"), err) 338 339 config.KeybaseService().(*KeybaseDaemonLocal).AddNewAssertionForTestOrBust( 340 "bob", "bob@twitter") 341 342 resolvedHandle, err := h.ResolveAgain(ctx, config.KBPKI(), nil, nil) 343 require.NoError(t, err) 344 345 dummyErr := errors.New("dummy") 346 err = makeRekeyReadErrorHelper(dummyErr, 347 rmd.ReadOnly(), resolvedHandle, uid, u) 348 require.Equal(t, NeedOtherRekeyError{"alice,bob", dummyErr}, err) 349 } 350 351 // Test that MakeSuccessor fails when the final bit is set. 352 353 func testRootMetadataFinalIsFinal(t *testing.T, ver kbfsmd.MetadataVer) { 354 tlfID := tlf.FakeID(0, tlf.Public) 355 h := makeFakeTlfHandle(t, 14, tlf.Public, nil, nil) 356 rmd, err := makeInitialRootMetadata(ver, tlfID, h) 357 require.NoError(t, err) 358 359 rmd.SetFinalBit() 360 _, err = rmd.MakeSuccessor(context.Background(), -1, nil, nil, nil, 361 nil, nil, kbfsmd.FakeID(1), true) 362 _, isFinalError := err.(kbfsmd.MetadataIsFinalError) 363 require.Equal(t, isFinalError, true) 364 } 365 366 func getAllUsersKeysForTest( 367 t *testing.T, config Config, rmd *RootMetadata, un string) []kbfscrypto.TLFCryptKey { 368 var keys []kbfscrypto.TLFCryptKey 369 for keyGen := kbfsmd.FirstValidKeyGen; keyGen <= rmd.LatestKeyGeneration(); keyGen++ { 370 key, err := config.KeyManager().(*KeyManagerStandard).getTLFCryptKeyUsingCurrentDevice( 371 context.Background(), rmd, keyGen, true) 372 require.NoError(t, err) 373 keys = append(keys, key) 374 } 375 return keys 376 } 377 378 // We always want misses for the tests below. 379 type dummyNoKeyCache struct { 380 } 381 382 func (kc *dummyNoKeyCache) GetTLFCryptKey(_ tlf.ID, _ kbfsmd.KeyGen) (kbfscrypto.TLFCryptKey, error) { 383 return kbfscrypto.TLFCryptKey{}, KeyCacheMissError{} 384 } 385 386 func (kc *dummyNoKeyCache) PutTLFCryptKey(_ tlf.ID, _ kbfsmd.KeyGen, _ kbfscrypto.TLFCryptKey) error { 387 return nil 388 } 389 390 // Test upconversion from MDv2 to MDv3 for a private folder. 391 func TestRootMetadataUpconversionPrivate(t *testing.T) { 392 config := MakeTestConfigOrBust(t, "alice", "bob", "charlie") 393 config.SetKeyCache(&dummyNoKeyCache{}) 394 ctx := context.Background() 395 defer CheckConfigAndShutdown(ctx, t, config) 396 397 tlfID := tlf.FakeID(1, tlf.Private) 398 h := parseTlfHandleOrBust(t, config, "alice,alice@twitter#bob,charlie@twitter,eve@reddit", tlf.Private, tlfID) 399 rmd, err := makeInitialRootMetadata(kbfsmd.InitialExtraMetadataVer, tlfID, h) 400 require.NoError(t, err) 401 require.Equal(t, kbfsmd.KeyGen(0), rmd.LatestKeyGeneration()) 402 require.Equal(t, kbfsmd.Revision(1), rmd.Revision()) 403 require.Equal(t, kbfsmd.InitialExtraMetadataVer, rmd.Version()) 404 405 // set some dummy numbers 406 diskUsage, refBytes, unrefBytes := uint64(12345), uint64(4321), uint64(1234) 407 rmd.SetDiskUsage(diskUsage) 408 rmd.SetRefBytes(refBytes) 409 rmd.SetUnrefBytes(unrefBytes) 410 // Make sure the MD looks readable. 411 rmd.data.Dir.BlockPointer = data.BlockPointer{ID: kbfsblock.FakeID(1)} 412 413 // key it once 414 done, _, err := config.KeyManager().Rekey(context.Background(), rmd, false) 415 require.NoError(t, err) 416 require.True(t, done) 417 require.Equal(t, kbfsmd.KeyGen(1), rmd.LatestKeyGeneration()) 418 require.Equal(t, kbfsmd.Revision(1), rmd.Revision()) 419 require.Equal(t, kbfsmd.InitialExtraMetadataVer, rmd.Version()) 420 require.Equal(t, 0, len(rmd.bareMd.(*kbfsmd.RootMetadataV2).RKeys[0].TLFReaderEphemeralPublicKeys)) 421 require.Equal(t, 1, len(rmd.bareMd.(*kbfsmd.RootMetadataV2).WKeys[0].TLFEphemeralPublicKeys)) 422 423 // revoke bob's device 424 _, bobID, err := config.KBPKI().Resolve( 425 context.Background(), "bob", keybase1.OfflineAvailability_NONE) 426 require.NoError(t, err) 427 bobUID, err := bobID.AsUser() 428 require.NoError(t, err) 429 430 RevokeDeviceForLocalUserOrBust(t, config, bobUID, 0) 431 432 // rekey it 433 done, _, err = config.KeyManager().Rekey(context.Background(), rmd, false) 434 require.NoError(t, err) 435 require.True(t, done) 436 require.Equal(t, kbfsmd.KeyGen(2), rmd.LatestKeyGeneration()) 437 require.Equal(t, kbfsmd.Revision(1), rmd.Revision()) 438 require.Equal(t, kbfsmd.InitialExtraMetadataVer, rmd.Version()) 439 require.Equal(t, 1, len(rmd.bareMd.(*kbfsmd.RootMetadataV2).WKeys[0].TLFEphemeralPublicKeys)) 440 require.Equal(t, 0, len(rmd.bareMd.(*kbfsmd.RootMetadataV2).RKeys[0].TLFReaderEphemeralPublicKeys)) 441 442 // prove charlie 443 config.KeybaseService().(*KeybaseDaemonLocal).AddNewAssertionForTestOrBust( 444 "charlie", "charlie@twitter") 445 446 // rekey it 447 done, _, err = config.KeyManager().Rekey(context.Background(), rmd, false) 448 require.NoError(t, err) 449 require.True(t, done) 450 require.Equal(t, kbfsmd.KeyGen(2), rmd.LatestKeyGeneration()) 451 require.Equal(t, kbfsmd.Revision(1), rmd.Revision()) 452 require.Equal(t, kbfsmd.InitialExtraMetadataVer, rmd.Version()) 453 require.Equal(t, 2, len(rmd.bareMd.(*kbfsmd.RootMetadataV2).WKeys[0].TLFEphemeralPublicKeys)) 454 require.Equal(t, 0, len(rmd.bareMd.(*kbfsmd.RootMetadataV2).RKeys[0].TLFReaderEphemeralPublicKeys)) 455 456 // add a device for charlie and rekey as charlie 457 _, charlieID, err := config.KBPKI().Resolve( 458 context.Background(), "charlie", keybase1.OfflineAvailability_NONE) 459 require.NoError(t, err) 460 charlieUID, err := charlieID.AsUser() 461 require.NoError(t, err) 462 463 config2 := ConfigAsUser(config, "charlie") 464 config2.SetKeyCache(&dummyNoKeyCache{}) 465 defer CheckConfigAndShutdown(ctx, t, config2) 466 AddDeviceForLocalUserOrBust(t, config, charlieUID) 467 AddDeviceForLocalUserOrBust(t, config2, charlieUID) 468 469 // rekey it 470 done, _, err = config2.KeyManager().Rekey(context.Background(), rmd, false) 471 require.NoError(t, err) 472 require.True(t, done) 473 require.Equal(t, kbfsmd.KeyGen(2), rmd.LatestKeyGeneration()) 474 require.Equal(t, kbfsmd.Revision(1), rmd.Revision()) 475 require.Equal(t, kbfsmd.InitialExtraMetadataVer, rmd.Version()) 476 require.Equal(t, 2, len(rmd.bareMd.(*kbfsmd.RootMetadataV2).WKeys[0].TLFEphemeralPublicKeys)) 477 require.Equal(t, 1, len(rmd.bareMd.(*kbfsmd.RootMetadataV2).RKeys[0].TLFReaderEphemeralPublicKeys)) 478 479 // override the metadata version 480 config.metadataVersion = kbfsmd.SegregatedKeyBundlesVer 481 482 // create an MDv3 successor 483 rmd2, err := rmd.MakeSuccessor(context.Background(), 484 config.MetadataVersion(), config.Codec(), 485 config.KeyManager(), config.KBPKI(), config.KBPKI(), nil, 486 kbfsmd.FakeID(1), true) 487 require.NoError(t, err) 488 require.Equal(t, kbfsmd.KeyGen(2), rmd2.LatestKeyGeneration()) 489 require.Equal(t, kbfsmd.Revision(2), rmd2.Revision()) 490 require.Equal(t, kbfsmd.SegregatedKeyBundlesVer, rmd2.Version()) 491 extra, ok := rmd2.extra.(*kbfsmd.ExtraMetadataV3) 492 require.True(t, ok) 493 require.True(t, extra.IsWriterKeyBundleNew()) 494 require.True(t, extra.IsReaderKeyBundleNew()) 495 496 // compare numbers 497 require.Equal(t, diskUsage, rmd2.DiskUsage()) 498 require.Equal(t, rmd.data.Dir, rmd2.data.Dir) 499 500 // These should be 0 since they are reset for successors. 501 require.Equal(t, uint64(0), rmd2.RefBytes()) 502 require.Equal(t, uint64(0), rmd2.UnrefBytes()) 503 504 // create and compare bare tlf handles (this verifies unresolved+resolved writer/reader sets are identical) 505 rmd.tlfHandle, rmd2.tlfHandle = nil, nil // avoid a panic due to the handle already existing 506 handle, err := rmd.MakeBareTlfHandle() 507 require.NoError(t, err) 508 handle2, err := rmd2.MakeBareTlfHandle() 509 require.NoError(t, err) 510 require.Equal(t, handle, handle2) 511 512 // compare tlf crypt keys 513 keys, err := config.KeyManager().GetTLFCryptKeyOfAllGenerations(context.Background(), rmd) 514 require.NoError(t, err) 515 require.Equal(t, 2, len(keys)) 516 517 keys2, err := config.KeyManager().GetTLFCryptKeyOfAllGenerations(context.Background(), rmd2) 518 require.NoError(t, err) 519 require.Equal(t, 2, len(keys2)) 520 require.Equal(t, keys, keys2) 521 522 // get each key generation for alice from each version of metadata 523 aliceKeys := getAllUsersKeysForTest(t, config, rmd, "alice") 524 aliceKeys2 := getAllUsersKeysForTest(t, config, rmd2, "alice") 525 526 // compare alice's keys 527 require.Equal(t, 2, len(aliceKeys)) 528 require.Equal(t, aliceKeys, aliceKeys2) 529 530 // get each key generation for charlie from each version of metadata 531 charlieKeys := getAllUsersKeysForTest(t, config2, rmd, "charlie") 532 charlieKeys2 := getAllUsersKeysForTest(t, config2, rmd2, "charlie") 533 534 // compare charlie's keys 535 require.Equal(t, 2, len(charlieKeys)) 536 require.Equal(t, charlieKeys, charlieKeys2) 537 538 // compare alice and charlie's keys 539 require.Equal(t, aliceKeys, charlieKeys) 540 541 // Rekeying again shouldn't change wkbNew/rkbNew. 542 err = rmd2.finalizeRekey(config.Codec()) 543 require.NoError(t, err) 544 extra, ok = rmd2.extra.(*kbfsmd.ExtraMetadataV3) 545 require.True(t, ok) 546 require.True(t, extra.IsWriterKeyBundleNew()) 547 require.True(t, extra.IsReaderKeyBundleNew()) 548 } 549 550 // Test upconversion from MDv2 to MDv3 for a public folder. 551 func TestRootMetadataUpconversionPublic(t *testing.T) { 552 ctx := context.Background() 553 config := MakeTestConfigOrBust(t, "alice", "bob") 554 defer CheckConfigAndShutdown(ctx, t, config) 555 556 tlfID := tlf.FakeID(1, tlf.Public) 557 h := parseTlfHandleOrBust( 558 t, config, "alice,bob,charlie@twitter", tlf.Public, tlfID) 559 rmd, err := makeInitialRootMetadata(kbfsmd.InitialExtraMetadataVer, tlfID, h) 560 require.NoError(t, err) 561 require.Equal(t, kbfsmd.PublicKeyGen, rmd.LatestKeyGeneration()) 562 require.Equal(t, kbfsmd.Revision(1), rmd.Revision()) 563 require.Equal(t, kbfsmd.InitialExtraMetadataVer, rmd.Version()) 564 565 // set some dummy numbers 566 diskUsage, refBytes, unrefBytes := uint64(12345), uint64(4321), uint64(1234) 567 rmd.SetDiskUsage(diskUsage) 568 rmd.SetRefBytes(refBytes) 569 rmd.SetUnrefBytes(unrefBytes) 570 571 // override the metadata version 572 config.metadataVersion = kbfsmd.SegregatedKeyBundlesVer 573 574 // create an MDv3 successor 575 rmd2, err := rmd.MakeSuccessor(context.Background(), 576 config.MetadataVersion(), config.Codec(), 577 config.KeyManager(), config.KBPKI(), config.KBPKI(), config, 578 kbfsmd.FakeID(1), true) 579 require.NoError(t, err) 580 require.Equal(t, kbfsmd.PublicKeyGen, rmd2.LatestKeyGeneration()) 581 require.Equal(t, kbfsmd.Revision(2), rmd2.Revision()) 582 require.Equal(t, kbfsmd.SegregatedKeyBundlesVer, rmd2.Version()) 583 // Do this instead of require.Nil because we want to assert 584 // that it's untyped nil. 585 require.True(t, rmd2.extra == nil) 586 587 // compare numbers 588 require.Equal(t, diskUsage, rmd2.DiskUsage()) 589 // we expect this and the below to be zero this time because the folder is public. 590 // they aren't reset in the private version because the private metadata isn't 591 // initialized therefor it's considered unreadable. 592 require.Equal(t, uint64(0), rmd2.RefBytes()) 593 require.Equal(t, uint64(0), rmd2.UnrefBytes()) 594 595 // create and compare bare tlf handles (this verifies unresolved+resolved writer sets are identical) 596 rmd.tlfHandle, rmd2.tlfHandle = nil, nil // avoid a panic due to the handle already existing 597 handle, err := rmd.MakeBareTlfHandle() 598 require.NoError(t, err) 599 handle2, err := rmd2.MakeBareTlfHandle() 600 require.NoError(t, err) 601 require.Equal(t, handle, handle2) 602 } 603 604 // Test upconversion from MDv2 to MDv3 for a private conflict folder. 605 // Regression test for KBFS-2381. 606 func TestRootMetadataUpconversionPrivateConflict(t *testing.T) { 607 ctx := context.Background() 608 config := MakeTestConfigOrBust(t, "alice", "bob") 609 defer CheckConfigAndShutdown(ctx, t, config) 610 611 tlfID := tlf.FakeID(1, tlf.Private) 612 h := parseTlfHandleOrBust( 613 t, config, "alice,bob (conflicted copy 2017-08-24)", tlf.Private, tlfID) 614 rmd, err := makeInitialRootMetadata(kbfsmd.InitialExtraMetadataVer, tlfID, h) 615 require.NoError(t, err) 616 require.Equal(t, kbfsmd.KeyGen(0), rmd.LatestKeyGeneration()) 617 require.Equal(t, kbfsmd.Revision(1), rmd.Revision()) 618 require.Equal(t, kbfsmd.InitialExtraMetadataVer, rmd.Version()) 619 require.NotNil(t, h.ConflictInfo()) 620 621 // set some dummy numbers 622 diskUsage, refBytes, unrefBytes := 623 uint64(12345), uint64(4321), uint64(1234) 624 rmd.SetDiskUsage(diskUsage) 625 rmd.SetRefBytes(refBytes) 626 rmd.SetUnrefBytes(unrefBytes) 627 // Make sure the MD looks readable. 628 rmd.data.Dir.BlockPointer = data.BlockPointer{ID: kbfsblock.FakeID(1)} 629 630 // key it once 631 done, _, err := config.KeyManager().Rekey(context.Background(), rmd, false) 632 require.NoError(t, err) 633 require.True(t, done) 634 require.Equal(t, kbfsmd.KeyGen(1), rmd.LatestKeyGeneration()) 635 require.Equal(t, kbfsmd.Revision(1), rmd.Revision()) 636 require.Equal(t, kbfsmd.InitialExtraMetadataVer, rmd.Version()) 637 require.Equal(t, 0, len(rmd.bareMd.(*kbfsmd.RootMetadataV2).RKeys[0].TLFReaderEphemeralPublicKeys)) 638 require.Equal(t, 1, len(rmd.bareMd.(*kbfsmd.RootMetadataV2).WKeys[0].TLFEphemeralPublicKeys)) 639 require.True(t, rmd.IsReadable()) 640 641 // override the metadata version 642 config.metadataVersion = kbfsmd.SegregatedKeyBundlesVer 643 644 // create an MDv3 successor 645 rmd2, err := rmd.MakeSuccessor(context.Background(), 646 config.MetadataVersion(), config.Codec(), 647 config.KeyManager(), config.KBPKI(), config.KBPKI(), config, 648 kbfsmd.FakeID(1), true) 649 require.NoError(t, err) 650 require.Equal(t, kbfsmd.KeyGen(1), rmd2.LatestKeyGeneration()) 651 require.Equal(t, kbfsmd.Revision(2), rmd2.Revision()) 652 require.Equal(t, kbfsmd.SegregatedKeyBundlesVer, rmd2.Version()) 653 extra, ok := rmd2.extra.(*kbfsmd.ExtraMetadataV3) 654 require.True(t, ok) 655 require.True(t, extra.IsWriterKeyBundleNew()) 656 require.True(t, extra.IsReaderKeyBundleNew()) 657 658 // Check the handle, but the cached handle in the MD is a direct copy... 659 require.Equal( 660 t, h.GetCanonicalPath(), rmd2.GetTlfHandle().GetCanonicalPath()) 661 // So also check that the conflict info is set in the MD itself. 662 require.NotNil(t, rmd2.bareMd.(*kbfsmd.RootMetadataV3).ConflictInfo) 663 } 664 665 // The server will be reusing IsLastModifiedBy and we don't want a client 666 // to be able to construct an MD that will crash the server. 667 func TestRootMetadataV3NoPanicOnWriterMismatch(t *testing.T) { 668 ctx := context.Background() 669 config := MakeTestConfigOrBust(t, "alice", "bob") 670 defer CheckConfigAndShutdown(ctx, t, config) 671 672 _, id, err := config.KBPKI().Resolve( 673 context.Background(), "alice", keybase1.OfflineAvailability_NONE) 674 require.NoError(t, err) 675 uid, err := id.AsUser() 676 require.NoError(t, err) 677 678 tlfID := tlf.FakeID(0, tlf.Private) 679 h := makeFakeTlfHandle(t, 14, tlf.Private, nil, nil) 680 rmd, err := makeInitialRootMetadata(kbfsmd.SegregatedKeyBundlesVer, tlfID, h) 681 require.NoError(t, err) 682 rmd.fakeInitialRekey() 683 rmd.SetLastModifyingWriter(uid) 684 rmd.SetLastModifyingUser(uid) 685 686 // sign with a mismatched writer 687 config2 := ConfigAsUser(config, "bob") 688 defer CheckConfigAndShutdown(ctx, t, config2) 689 rmds, err := SignBareRootMetadata( 690 context.Background(), config.Codec(), config.Crypto(), config2.Crypto(), rmd.bareMd, time.Now()) 691 require.NoError(t, err) 692 693 // verify last modifier 694 session, err := config.KBPKI().GetCurrentSession(context.Background()) 695 require.NoError(t, err) 696 session2, err := config2.KBPKI().GetCurrentSession(context.Background()) 697 require.NoError(t, err) 698 699 err = rmds.IsLastModifiedBy(uid, session.VerifyingKey) 700 require.EqualError(t, err, fmt.Sprintf("Last writer verifying key %s != %s", session2.VerifyingKey, session.VerifyingKey)) 701 } 702 703 // Test that a reader can't upconvert a private folder from v2 to v3. 704 func TestRootMetadataReaderUpconversionPrivate(t *testing.T) { 705 ctx := context.Background() 706 configWriter := MakeTestConfigOrBust(t, "alice", "bob") 707 configWriter.SetKeyCache(&dummyNoKeyCache{}) 708 defer CheckConfigAndShutdown(ctx, t, configWriter) 709 710 tlfID := tlf.FakeID(1, tlf.Private) 711 h := parseTlfHandleOrBust(t, configWriter, "alice#bob", tlf.Private, tlfID) 712 rmd, err := makeInitialRootMetadata(kbfsmd.InitialExtraMetadataVer, tlfID, h) 713 require.NoError(t, err) 714 require.Equal(t, kbfsmd.KeyGen(0), rmd.LatestKeyGeneration()) 715 require.Equal(t, kbfsmd.Revision(1), rmd.Revision()) 716 require.Equal(t, kbfsmd.PreExtraMetadataVer, rmd.Version()) 717 718 // set some dummy numbers 719 diskUsage, refBytes, unrefBytes := uint64(12345), uint64(4321), uint64(1234) 720 rmd.SetDiskUsage(diskUsage) 721 rmd.SetRefBytes(refBytes) 722 rmd.SetUnrefBytes(unrefBytes) 723 724 // Have the writer key it first. 725 done, _, err := configWriter.KeyManager().Rekey( 726 context.Background(), rmd, false) 727 require.NoError(t, err) 728 require.True(t, done) 729 require.Equal(t, kbfsmd.KeyGen(1), rmd.LatestKeyGeneration()) 730 require.Equal(t, kbfsmd.Revision(1), rmd.Revision()) 731 require.Equal(t, kbfsmd.PreExtraMetadataVer, rmd.Version()) 732 require.Equal(t, 1, len(rmd.bareMd.(*kbfsmd.RootMetadataV2).WKeys[0].TLFEphemeralPublicKeys)) 733 require.Equal(t, 0, len(rmd.bareMd.(*kbfsmd.RootMetadataV2).RKeys[0].TLFReaderEphemeralPublicKeys)) 734 735 // Set the private MD, to make sure it gets copied properly during 736 // upconversion. 737 _, aliceID, err := configWriter.KBPKI().Resolve( 738 context.Background(), "alice", keybase1.OfflineAvailability_NONE) 739 require.NoError(t, err) 740 aliceUID, err := aliceID.AsUser() 741 require.NoError(t, err) 742 743 err = encryptMDPrivateData(context.Background(), configWriter.Codec(), 744 configWriter.Crypto(), configWriter.Crypto(), 745 configWriter.KeyManager(), aliceUID, rmd) 746 require.NoError(t, err) 747 748 // add a device for bob and rekey as bob 749 _, bobID, err := configWriter.KBPKI().Resolve( 750 context.Background(), "bob", keybase1.OfflineAvailability_NONE) 751 require.NoError(t, err) 752 bobUID, err := bobID.AsUser() 753 require.NoError(t, err) 754 755 configReader := ConfigAsUser(configWriter, "bob") 756 configReader.SetKeyCache(&dummyNoKeyCache{}) 757 defer CheckConfigAndShutdown(ctx, t, configReader) 758 AddDeviceForLocalUserOrBust(t, configWriter, bobUID) 759 AddDeviceForLocalUserOrBust(t, configReader, bobUID) 760 761 // Override the metadata version, make a successor, and rekey as 762 // reader. This should keep the version the same, since readers 763 // can't upconvert. 764 configReader.metadataVersion = kbfsmd.SegregatedKeyBundlesVer 765 rmd2, err := rmd.MakeSuccessor(context.Background(), 766 configReader.MetadataVersion(), configReader.Codec(), 767 configReader.KeyManager(), configReader.KBPKI(), 768 configReader.KBPKI(), configReader, kbfsmd.FakeID(1), false) 769 require.NoError(t, err) 770 require.Equal(t, kbfsmd.KeyGen(1), rmd2.LatestKeyGeneration()) 771 require.Equal(t, kbfsmd.Revision(2), rmd2.Revision()) 772 require.Equal(t, kbfsmd.PreExtraMetadataVer, rmd2.Version()) 773 // Do this instead of require.Nil because we want to assert 774 // that it's untyped nil. 775 require.True(t, rmd2.extra == nil) 776 done, _, err = configReader.KeyManager().Rekey( 777 context.Background(), rmd2, false) 778 require.NoError(t, err) 779 require.True(t, done) 780 require.Equal(t, kbfsmd.KeyGen(1), rmd2.LatestKeyGeneration()) 781 require.Equal(t, kbfsmd.Revision(2), rmd2.Revision()) 782 require.Equal(t, kbfsmd.PreExtraMetadataVer, rmd2.Version()) 783 require.True(t, rmd2.IsWriterMetadataCopiedSet()) 784 require.True(t, bytes.Equal(rmd.GetSerializedPrivateMetadata(), 785 rmd2.GetSerializedPrivateMetadata())) 786 787 rmds, err := SignBareRootMetadata(context.Background(), 788 configReader.Codec(), configReader.Crypto(), configReader.Crypto(), 789 rmd2.bareMd, configReader.Clock().Now()) 790 require.NoError(t, err) 791 err = rmds.IsValidAndSigned( 792 ctx, configReader.Codec(), nil, rmd2.extra, 793 keybase1.OfflineAvailability_NONE) 794 require.NoError(t, err) 795 } 796 797 // Check writer/reader methods with teams 798 func TestRootMetadataTeamMembership(t *testing.T) { 799 config := MakeTestConfigOrBust(t, "alice", "bob", "charlie") 800 ctx := context.Background() 801 defer CheckConfigAndShutdown(ctx, t, config) 802 803 teamInfos := AddEmptyTeamsForTestOrBust(t, config, "t1") 804 tid := teamInfos[0].TID 805 806 tlfID := tlf.FakeID(1, tlf.SingleTeam) 807 h := tlfhandle.NewHandle( 808 tlf.SingleTeam, 809 map[keybase1.UserOrTeamID]kbname.NormalizedUsername{ 810 tid.AsUserOrTeam(): "t1", 811 }, nil, nil, "t1", tlf.NullID) 812 rmd, err := makeInitialRootMetadata(kbfsmd.InitialExtraMetadataVer, tlfID, h) 813 require.NoError(t, err) 814 815 getUser := func(name string) (keybase1.UID, kbfscrypto.VerifyingKey) { 816 _, id, err := config.KBPKI().Resolve( 817 context.Background(), name, keybase1.OfflineAvailability_NONE) 818 require.NoError(t, err) 819 uid, err := id.AsUser() 820 require.NoError(t, err) 821 822 userInfo, err := config.KeybaseService().LoadUserPlusKeys( 823 context.Background(), uid, keybase1.KID(""), 824 keybase1.OfflineAvailability_NONE) 825 require.NoError(t, err) 826 827 return uid, userInfo.VerifyingKeys[0] 828 } 829 aliceUID, aliceKey := getUser("alice") 830 bobUID, bobKey := getUser("bob") 831 charlieUID, charlieKey := getUser("charlie") 832 833 // No user should be able to read this yet. 834 checkWriter := func(uid keybase1.UID, key kbfscrypto.VerifyingKey, 835 expectedIsWriter bool) { 836 isWriter, err := rmd.IsWriter(ctx, config.KBPKI(), config, uid, key) 837 require.NoError(t, err) 838 require.Equal(t, expectedIsWriter, isWriter) 839 } 840 checkReader := func(uid keybase1.UID, expectedIsReader bool) { 841 isReader, err := rmd.IsReader(ctx, config.KBPKI(), config, uid) 842 require.NoError(t, err) 843 require.Equal(t, expectedIsReader, isReader) 844 } 845 checkWriter(aliceUID, aliceKey, false) 846 checkWriter(bobUID, bobKey, false) 847 checkWriter(charlieUID, charlieKey, false) 848 checkReader(aliceUID, false) 849 checkReader(bobUID, false) 850 checkReader(charlieUID, false) 851 852 // Make bob a writer. 853 AddTeamWriterForTestOrBust(t, config, tid, bobUID) 854 checkWriter(aliceUID, aliceKey, false) 855 checkWriter(bobUID, bobKey, true) 856 checkWriter(charlieUID, charlieKey, false) 857 checkReader(aliceUID, false) 858 checkReader(bobUID, true) 859 checkReader(charlieUID, false) 860 861 // Make alice a writer, and charlie a reader. 862 AddTeamWriterForTestOrBust(t, config, tid, aliceUID) 863 AddTeamReaderForTestOrBust(t, config, tid, charlieUID) 864 checkWriter(aliceUID, aliceKey, true) 865 checkWriter(bobUID, bobKey, true) 866 checkWriter(charlieUID, charlieKey, false) 867 checkReader(aliceUID, true) 868 checkReader(bobUID, true) 869 checkReader(charlieUID, true) 870 871 // Promote charlie to writer. 872 AddTeamWriterForTestOrBust(t, config, tid, charlieUID) 873 checkWriter(aliceUID, aliceKey, true) 874 checkWriter(bobUID, bobKey, true) 875 checkWriter(charlieUID, charlieKey, true) 876 checkReader(aliceUID, true) 877 checkReader(bobUID, true) 878 checkReader(charlieUID, true) 879 } 880 881 // Check that MakeSuccessor gets the right key gen for teams. 882 func TestRootMetadataTeamMakeSuccessor(t *testing.T) { 883 config := MakeTestConfigOrBust(t, "alice") 884 ctx := context.Background() 885 defer CheckConfigAndShutdown(ctx, t, config) 886 887 teamInfos := AddEmptyTeamsForTestOrBust(t, config, "t1") 888 tid := teamInfos[0].TID 889 890 tlfID := tlf.FakeID(1, tlf.SingleTeam) 891 h := tlfhandle.NewHandle( 892 tlf.SingleTeam, 893 map[keybase1.UserOrTeamID]kbname.NormalizedUsername{ 894 tid.AsUserOrTeam(): "t1", 895 }, nil, nil, "t1", tlf.NullID) 896 rmd, err := makeInitialRootMetadata(kbfsmd.SegregatedKeyBundlesVer, tlfID, h) 897 require.NoError(t, err) 898 rmd.bareMd.SetLatestKeyGenerationForTeamTLF(teamInfos[0].LatestKeyGen) 899 // Make sure the MD looks readable. 900 rmd.data.Dir.BlockPointer = data.BlockPointer{ID: kbfsblock.FakeID(1)} 901 902 firstKeyGen := rmd.LatestKeyGeneration() 903 require.Equal(t, kbfsmd.FirstValidKeyGen, firstKeyGen) 904 905 rmd2, err := rmd.MakeSuccessor(context.Background(), 906 config.MetadataVersion(), config.Codec(), 907 config.KeyManager(), config.KBPKI(), config.KBPKI(), config, 908 kbfsmd.FakeID(1), true) 909 require.NoError(t, err) 910 911 // No increase yet. 912 kg := rmd2.LatestKeyGeneration() 913 require.Equal(t, firstKeyGen, kg) 914 915 AddTeamKeyForTestOrBust(t, config, tid) 916 917 rmd3, err := rmd2.MakeSuccessor(context.Background(), 918 config.MetadataVersion(), config.Codec(), 919 config.KeyManager(), config.KBPKI(), config.KBPKI(), config, 920 kbfsmd.FakeID(2), true) 921 require.NoError(t, err) 922 923 // Should have been bumped by one. 924 kg = rmd3.LatestKeyGeneration() 925 require.Equal(t, firstKeyGen+1, kg) 926 } 927 928 func TestRootMetadata(t *testing.T) { 929 tests := []func(*testing.T, kbfsmd.MetadataVer){ 930 testRootMetadataGetTlfHandlePublic, 931 testRootMetadataGetTlfHandlePrivate, 932 testRootMetadataLatestKeyGenerationPrivate, 933 testRootMetadataLatestKeyGenerationPublic, 934 testMakeRekeyReadError, 935 testMakeRekeyReadErrorResolvedHandle, 936 testRootMetadataFinalIsFinal, 937 } 938 runTestsOverMetadataVers(t, "testRootMetadata", tests) 939 }