github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libkbfs/md_ops.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 "fmt" 9 "sync" 10 "time" 11 12 "github.com/keybase/client/go/kbfs/data" 13 "github.com/keybase/client/go/kbfs/idutil" 14 "github.com/keybase/client/go/kbfs/kbfsblock" 15 "github.com/keybase/client/go/kbfs/kbfscrypto" 16 "github.com/keybase/client/go/kbfs/kbfsmd" 17 "github.com/keybase/client/go/kbfs/tlf" 18 "github.com/keybase/client/go/kbfs/tlfhandle" 19 kbname "github.com/keybase/client/go/kbun" 20 "github.com/keybase/client/go/libkb" 21 "github.com/keybase/client/go/logger" 22 "github.com/keybase/client/go/protocol/keybase1" 23 "github.com/pkg/errors" 24 "golang.org/x/net/context" 25 "golang.org/x/sync/errgroup" 26 ) 27 28 const ( 29 // Update 2024-02-16: we decided to increase the merkle gap check to 4 days 30 // in case mdmerkle goes down, to give us more time to fix it. 31 maxAllowedMerkleGapServer = 4 * (time.Hour * 24) 32 maxAllowedMerkleGap = maxAllowedMerkleGapServer + 15*time.Minute 33 34 // merkleGapEnforcementStartString indicates when the mdserver 35 // started rejecting new writes based on the lack of recent merkle 36 // updates (according to `maxAllowedMerkleGap` above). 37 merkleGapEnforcementStartString = "2018-06-14T16:21:30-07:00" 38 ) 39 40 var merkleGapEnforcementStart time.Time 41 42 func init() { 43 var err error 44 merkleGapEnforcementStart, err = time.Parse( 45 "2006-01-02T15:04:05-07:00", merkleGapEnforcementStartString) 46 if err != nil { 47 // Can never happen without a bad global const string. 48 panic(err) 49 } 50 } 51 52 // MDOpsStandard provides plaintext RootMetadata objects to upper 53 // layers, and processes RootMetadataSigned objects (encrypted and 54 // signed) suitable for passing to/from the MDServer backend. 55 type MDOpsStandard struct { 56 config Config 57 log logger.Logger 58 vlog *libkb.VDebugLog 59 60 lock sync.Mutex 61 // For each TLF, maps an MD revision representing the next MD 62 // after a device revoke, with the minimum revision number that's 63 // been validated in chain up to the given MD revision. That is, 64 // for TLF 1, if we have a next revision of 1000, and we've 65 // validated that MDs 100-1000 form a valid chain, then the map 66 // would contain: {1: {1000: 100}} 67 leafChainsValidated map[tlf.ID]map[kbfsmd.Revision]kbfsmd.Revision 68 } 69 70 // NewMDOpsStandard returns a new MDOpsStandard 71 func NewMDOpsStandard(config Config) *MDOpsStandard { 72 log := config.MakeLogger("") 73 return &MDOpsStandard{ 74 config: config, 75 log: log, 76 vlog: config.MakeVLogger(log), 77 leafChainsValidated: make( 78 map[tlf.ID]map[kbfsmd.Revision]kbfsmd.Revision), 79 } 80 } 81 82 // convertVerifyingKeyError gives a better error when the TLF was 83 // signed by a key that is no longer associated with the last writer. 84 func (md *MDOpsStandard) convertVerifyingKeyError(ctx context.Context, 85 rmds *RootMetadataSigned, handle *tlfhandle.Handle, err error) error { 86 if _, ok := err.(VerifyingKeyNotFoundError); !ok { 87 return err 88 } 89 90 tlf := handle.GetCanonicalPath() 91 writer, nameErr := md.config.KBPKI().GetNormalizedUsername( 92 ctx, rmds.MD.LastModifyingWriter().AsUserOrTeam(), 93 md.config.OfflineAvailabilityForPath(tlf)) 94 if nameErr != nil { 95 writer = kbname.NormalizedUsername("uid: " + 96 rmds.MD.LastModifyingWriter().String()) 97 } 98 md.log.CDebugf(ctx, "Unverifiable update for TLF %s: %+v", 99 rmds.MD.TlfID(), err) 100 return UnverifiableTlfUpdateError{tlf, writer, err} 101 } 102 103 type ctxMDOpsSkipKeyVerificationType int 104 105 // This context key indicates that we should skip verification of 106 // revoked keys, to avoid recursion issues. Any resulting MD 107 // that skips verification shouldn't be trusted or cached. 108 const ctxMDOpsSkipKeyVerification ctxMDOpsSkipKeyVerificationType = 1 109 110 func (md *MDOpsStandard) decryptMerkleLeaf( 111 ctx context.Context, rmd ReadOnlyRootMetadata, 112 kbfsRoot *kbfsmd.MerkleRoot, leafBytes []byte) ( 113 leaf *kbfsmd.MerkleLeaf, err error) { 114 var eLeaf kbfsmd.EncryptedMerkleLeaf 115 err = md.config.Codec().Decode(leafBytes, &eLeaf) 116 if err != nil { 117 return nil, err 118 } 119 120 if rmd.TypeForKeying() == tlf.TeamKeying { 121 // For teams, only the Keybase service has access to the 122 // private key that can decrypt the data, so send the request 123 // over to the crypto client. 124 cryptoLeaf := kbfscrypto.MakeEncryptedMerkleLeaf( 125 eLeaf.Version, eLeaf.EncryptedData, kbfsRoot.Nonce) 126 teamID := rmd.GetTlfHandle().FirstResolvedWriter().AsTeamOrBust() 127 // The merkle tree doesn't yet record which team keygen is 128 // used to encrypt a merkle leaf, so just use 1 as the min 129 // number and let the service scan. In the future, we should 130 // have the server record the keygen in the merkle leaf header 131 // and use that instead. (Note that "team keygen" is 132 // completely separate from "application keygen", so we can't 133 // just use `rmd.LatestKeyGeneration()` here.) 134 minKeyGen := keybase1.PerTeamKeyGeneration(1) 135 md.vlog.CLogf( 136 ctx, libkb.VLog1, 137 "Decrypting Merkle leaf for team %s with min key generation %d", 138 teamID, minKeyGen) 139 leafBytes, err := md.config.Crypto().DecryptTeamMerkleLeaf( 140 ctx, teamID, *kbfsRoot.EPubKey, cryptoLeaf, minKeyGen) 141 if err != nil { 142 return nil, err 143 } 144 var leaf kbfsmd.MerkleLeaf 145 if err := md.config.Codec().Decode(leafBytes, &leaf); err != nil { 146 return nil, err 147 } 148 return &leaf, nil 149 } 150 151 // The private key we need to decrypt the leaf does not live in 152 // key bundles; it lives only in the MDs that were part of a 153 // specific keygen. But we don't yet know what the keygen was, or 154 // what MDs were part of it, except that they have to have a 155 // larger revision number than the given `rmd`. So all we can do 156 // is iterate up from `rmd`, looking for a key that will unlock 157 // the leaf. 158 // 159 // Luckily, in the common case we'll be trying to verify the head 160 // of the folder, so we should be able to use 161 // rmd.data.TLFPrivateKey. 162 163 // Fetch the latest MD so we have all possible TLF crypt keys 164 // available to this device. 165 head, err := md.getForTLF( 166 ctx, rmd.TlfID(), rmd.BID(), rmd.MergedStatus(), nil) 167 if err != nil { 168 return nil, err 169 } 170 171 var uid keybase1.UID 172 if rmd.TlfID().Type() != tlf.Public { 173 session, err := md.config.KBPKI().GetCurrentSession(ctx) 174 if err != nil { 175 return nil, err 176 } 177 uid = session.UID 178 } 179 180 currRmd := rmd 181 for { 182 // If currRmd isn't readable, keep fetching MDs until it can 183 // be read. Then try currRmd.data.TLFPrivateKey to decrypt 184 // the leaf. If it doesn't work, fetch MDs until we find the 185 // next keygen, and continue the loop. 186 187 privKey := currRmd.data.TLFPrivateKey 188 if !currRmd.IsReadable() { 189 pmd, err := decryptMDPrivateData( 190 ctx, md.config.Codec(), md.config.Crypto(), 191 md.config.BlockCache(), md.config.BlockOps(), 192 md.config.KeyManager(), md.config.KBPKI(), md.config, 193 md.config.Mode(), uid, currRmd.GetSerializedPrivateMetadata(), 194 currRmd, head.ReadOnlyRootMetadata, md.log) 195 if err != nil { 196 return nil, err 197 } 198 privKey = pmd.TLFPrivateKey 199 } 200 currKeyGen := currRmd.LatestKeyGeneration() 201 if privKey == (kbfscrypto.TLFPrivateKey{}) { 202 return nil, errors.Errorf( 203 "Can't get TLF private key for key generation %d", currKeyGen) 204 } 205 206 mLeaf, err := eLeaf.Decrypt( 207 md.config.Codec(), privKey, kbfsRoot.Nonce, *kbfsRoot.EPubKey) 208 switch errors.Cause(err).(type) { 209 case nil: 210 return &mLeaf, nil 211 case libkb.DecryptionError: 212 // Fall-through to try another key generation. 213 default: 214 return nil, err 215 } 216 217 md.vlog.CLogf( 218 ctx, libkb.VLog1, "Key generation %d didn't work; searching for "+ 219 "the next one", currKeyGen) 220 221 fetchLoop: 222 for { 223 start := currRmd.Revision() + 1 224 end := start + maxMDsAtATime - 1 // range is inclusive 225 nextRMDs, err := getMergedMDUpdatesWithEnd( 226 ctx, md.config, currRmd.TlfID(), start, end, nil) 227 if err != nil { 228 return nil, err 229 } 230 231 for _, nextRmd := range nextRMDs { 232 if nextRmd.LatestKeyGeneration() > currKeyGen { 233 md.vlog.CLogf( 234 ctx, libkb.VLog1, "Revision %d has key gen %d", 235 nextRmd.Revision(), nextRmd.LatestKeyGeneration()) 236 currRmd = nextRmd.ReadOnlyRootMetadata 237 break fetchLoop 238 } 239 } 240 241 if len(nextRMDs) < maxMDsAtATime { 242 md.log.CDebugf(ctx, 243 "We tried all revisions and couldn't find a working keygen") 244 return nil, errors.Errorf("Can't decrypt merkle leaf") 245 } 246 currRmd = nextRMDs[len(nextRMDs)-1].ReadOnly() 247 } 248 } 249 } 250 251 func (md *MDOpsStandard) makeMerkleLeaf( 252 ctx context.Context, rmd ReadOnlyRootMetadata, 253 kbfsRoot *kbfsmd.MerkleRoot, leafBytes []byte) ( 254 leaf *kbfsmd.MerkleLeaf, err error) { 255 if rmd.TlfID().Type() != tlf.Public { 256 return md.decryptMerkleLeaf(ctx, rmd, kbfsRoot, leafBytes) 257 } 258 259 var mLeaf kbfsmd.MerkleLeaf 260 err = md.config.Codec().Decode(leafBytes, &mLeaf) 261 if err != nil { 262 return nil, err 263 } 264 return &mLeaf, nil 265 } 266 267 func mdToMerkleTreeID(irmd ImmutableRootMetadata) keybase1.MerkleTreeID { 268 switch irmd.TlfID().Type() { 269 case tlf.Private: 270 return keybase1.MerkleTreeID_KBFS_PRIVATE 271 case tlf.Public: 272 return keybase1.MerkleTreeID_KBFS_PUBLIC 273 case tlf.SingleTeam: 274 return keybase1.MerkleTreeID_KBFS_PRIVATETEAM 275 default: 276 panic(fmt.Sprintf("Unexpected TLF keying type: %d", 277 irmd.TypeForKeying())) 278 } 279 } 280 281 func (md *MDOpsStandard) checkMerkleTimes(ctx context.Context, 282 latestRootTime time.Time, kbfsRoot *kbfsmd.MerkleRoot, 283 timeToCheck time.Time, allowedGapSinceMerkle time.Duration) error { 284 var latestKbfsTime time.Time 285 if kbfsRoot != nil { 286 latestKbfsTime = time.Unix(kbfsRoot.Timestamp, 0) 287 } 288 289 rootGap := timeToCheck.Sub(latestRootTime) 290 kbfsGap := timeToCheck.Sub(latestKbfsTime) 291 gapBound := allowedGapSinceMerkle 292 293 // A negative gap means that we expect the merkle roots to have 294 // happened second. 295 if allowedGapSinceMerkle < 0 { 296 if rootGap > 0 || kbfsGap > 0 { 297 return errors.Errorf( 298 "Roots were unexpectedly made before event being checked, "+ 299 "timeToCheck=%s, latestRootTime=%s, latestKbfsTime=%s", 300 timeToCheck.Format(time.RFC3339Nano), 301 latestRootTime.Format(time.RFC3339Nano), 302 latestKbfsTime.Format(time.RFC3339Nano)) 303 } 304 rootGap = -rootGap 305 kbfsGap = -kbfsGap 306 gapBound = -gapBound 307 } 308 309 // If it's been too long since the last published Merkle root, 310 // we can't trust what the server told us. 311 if rootGap > gapBound { 312 return errors.Errorf("Gap too large between event and global Merkle "+ 313 "roots: gap=%s, timeToCheck=%s, latestRootTime=%s", 314 allowedGapSinceMerkle, 315 timeToCheck.Format(time.RFC3339Nano), 316 latestRootTime.Format(time.RFC3339Nano)) 317 } 318 if kbfsGap > gapBound { 319 return errors.Errorf("Gap too large between event and KBFS Merkle "+ 320 "roots: gap=%s, timeToCheck=%s, latestRootTime=%s", 321 allowedGapSinceMerkle, 322 timeToCheck.Format(time.RFC3339Nano), 323 latestKbfsTime.Format(time.RFC3339Nano)) 324 } 325 return nil 326 } 327 328 // startOfValidatedChainForLeaf returns the earliest revision in the 329 // chain leading up to `leafRev` that's been validated so far. If no 330 // validations have occurred yet, it returns `leafRev`. 331 func (md *MDOpsStandard) startOfValidatedChainForLeaf( 332 tlfID tlf.ID, leafRev kbfsmd.Revision) kbfsmd.Revision { 333 md.lock.Lock() 334 defer md.lock.Unlock() 335 revs, ok := md.leafChainsValidated[tlfID] 336 if !ok { 337 return leafRev 338 } 339 min, ok := revs[leafRev] 340 if !ok { 341 return leafRev 342 } 343 return min 344 } 345 346 func (md *MDOpsStandard) mdserver(ctx context.Context) ( 347 mds MDServer, err error) { 348 // The init code sets the MDOps before it sets the MDServer, and 349 // so it might be used before the MDServer is available (e.g., if 350 // the Keybase service is established before the MDServer is set, 351 // and it tries to look up handles for the user's public and 352 // private TLFs). So just wait until it's available, which should 353 // be happen very quickly. 354 first := true 355 for mds = md.config.MDServer(); mds == nil; mds = md.config.MDServer() { 356 if first { 357 md.log.CDebugf(ctx, "Waiting for mdserver") 358 first = false 359 } 360 time.Sleep(10 * time.Millisecond) 361 select { 362 case <-ctx.Done(): 363 return nil, ctx.Err() 364 default: 365 } 366 } 367 return mds, nil 368 } 369 370 func (md *MDOpsStandard) checkRevisionCameBeforeMerkle( 371 ctx context.Context, rmds *RootMetadataSigned, 372 verifyingKey kbfscrypto.VerifyingKey, irmd ImmutableRootMetadata, 373 root keybase1.MerkleRootV2, timeToCheck time.Time) (err error) { 374 ctx = context.WithValue(ctx, ctxMDOpsSkipKeyVerification, struct{}{}) 375 // This gives us the KBFS merkle root that comes after the KBFS merkle 376 // root right after the one included by `root`. In other words, if the 377 // KBFS merkle root included in `root` is K0, the returned KBFS merkle 378 // root `kbfsRoot` here would be K2. 379 // 380 // Since `root` is the merkle root included by the revoke signature, 381 // anything written by the revoked device after K2 is not legit. The reason 382 // why we don't check K1 is that when K1 was built, it's possible that it 383 // only included writes happening right before the revoke happened. For 384 // example: 385 // 386 // - 8:00am mdmerkle starts to run 387 // - 8:01am mdmerkle scans TLF /keybase/private/alice 388 // - 8:02am Alice's device "Playstation 4" writes to her TLF 389 // /keybase/private/alice 390 // - 8:03am Alice revokes her device "Playstation 4", referencing a 391 // global merkle root that includes KBFS merkle K0 392 // - 8:07am mdmerkle finishes building the merkle tree and publish K1, 393 // which includes the head MD from /keybase/private/alice from 8:01, 394 // the one before the write happened at 8:02am. 395 // - 9:00am mdmerkle starts to run again, producing a KBFS merkle tree 396 // K2. 397 // 398 // Looking at the per TLF metadata chain, the writes happened at 8:02 399 // happened after the MD included in K1, but it was before the revoke and 400 // was legit. So we have to compare with K2 instead of K1. 401 // 402 // To protect against a malicious server indefinitely halting building 403 // KBFS merkle trees with the purpose of slipping in malicious writes 404 // from a revoked device, we have a "contract" with the mdserver that 405 // any writes happening after a grace period of 406 // `maxAllowedMerkleGapServer` after the last KBFS merkle tree was 407 // published should be rejected. In other words, KBFS should become 408 // readonly if `maxAllowedMerkleGapServer` has passed since last KBFS 409 // merkle tree was published. We add a small error window to it, and 410 // enforce in the client that any MD with a gap greater than 411 // `maxAllowedMerkleGap` since last KBFS merkle tree is illegal. 412 // 413 // However there's no way get a trustable timestamp for the metadata 414 // update happening at 8:02am when we haven't verified that metadata yet, 415 // we have to proxy it to some sort of ordering from merkle trees. Here we 416 // are using K2 as that proxy. Since we already need to guarantee the 417 // metadata in question has to happen before K2, we just need to make sure 418 // K2 happens within `maxAllowedMerkleGap` since the revoke happened. 419 // 420 // Unfortunately this means if mdmerkle takes longer than 421 // `maxAllowedMerkleGap` to build two trees, and a device both writes to a 422 // TLF and then gets revoked within that gap (and those writes are the most 423 // recent writes to the TLF), there's no way for us to know for sure the 424 // write is legit, from merkle tree perspective, and future reads of the 425 // TLF will fail without manual intervention. 426 kbfsRoot, merkleNodes, rootSeqno, err := 427 md.config.MDCache().GetNextMD(rmds.MD.TlfID(), root.Seqno) 428 switch errors.Cause(err).(type) { 429 case nil: 430 case NextMDNotCachedError: 431 md.vlog.CLogf( 432 ctx, libkb.VLog1, "Finding next MD for TLF %s after global root %d", 433 rmds.MD.TlfID(), root.Seqno) 434 mdserv, err := md.mdserver(ctx) 435 if err != nil { 436 return err 437 } 438 kbfsRoot, merkleNodes, rootSeqno, err = 439 mdserv.FindNextMD(ctx, rmds.MD.TlfID(), root.Seqno) 440 if err != nil { 441 return err 442 } 443 err = md.config.MDCache().PutNextMD( 444 rmds.MD.TlfID(), root.Seqno, kbfsRoot, merkleNodes, rootSeqno) 445 if err != nil { 446 return err 447 } 448 default: 449 return err 450 } 451 452 if len(merkleNodes) == 0 { 453 // This can happen legitimately if we are still inside the 454 // error window and no new merkle trees have been made yet, or 455 // the server could be lying to us. 456 md.log.CDebugf(ctx, "The server claims there haven't been any "+ 457 "KBFS merkle trees published since the merkle root") 458 459 // Check the most recent global merkle root and KBFS merkle 460 // root ctimes and make sure they fall within the expected 461 // error window with respect to the revocation. 462 _, latestRootTime, err := md.config.KBPKI().GetCurrentMerkleRoot(ctx) 463 if err != nil { 464 return err 465 } 466 treeID := mdToMerkleTreeID(irmd) 467 // TODO: cache the latest KBFS merkle root somewhere for a while? 468 mdserv, err := md.mdserver(ctx) 469 if err != nil { 470 return err 471 } 472 latestKbfsRoot, err := mdserv.GetMerkleRootLatest(ctx, treeID) 473 if err != nil { 474 return err 475 } 476 serverOffset, _ := mdserv.OffsetFromServerTime() 477 if (serverOffset < 0 && serverOffset < -time.Hour) || 478 (serverOffset > 0 && serverOffset > time.Hour) { 479 return errors.Errorf("The offset between the server clock "+ 480 "and the local clock is too large to check the revocation "+ 481 "time: %s", serverOffset) 482 } 483 currServerTime := md.config.Clock().Now().Add(-serverOffset) 484 err = md.checkMerkleTimes( 485 ctx, latestRootTime, latestKbfsRoot, currServerTime, 486 maxAllowedMerkleGap) 487 if err != nil { 488 return err 489 } 490 491 // Verify the chain up to the current head. By using `ctx`, 492 // we'll avoid infinite loops in the writer-key-checking code 493 // by skipping revoked key verification. This is ok, because 494 // we only care about the hash chain for the purposes of 495 // verifying `irmd`. 496 chain, err := getMergedMDUpdates( 497 ctx, md.config, irmd.TlfID(), irmd.Revision()+1, nil) 498 if err != nil { 499 return err 500 } 501 if len(chain) > 0 { 502 err = irmd.CheckValidSuccessor( 503 irmd.mdID, chain[0].ReadOnlyRootMetadata) 504 if err != nil { 505 return err 506 } 507 } 508 509 // TODO: Also eventually check the blockchain-published merkles to 510 // make sure the server isn't lying (though that will have a 511 // much larger error window). 512 return nil 513 } 514 515 if !timeToCheck.IsZero() { 516 // Check the gap between the event and the global/KBFS roots 517 // that include the event, to make sure they fall within the 518 // expected error window. The server didn't begin enforcing this 519 // until some time into KBFS's existence though. 520 if timeToCheck.After(merkleGapEnforcementStart) { 521 // TODO(KBFS-2954): get the right root time for the 522 // corresponding global root. 523 latestRootTime := time.Unix(kbfsRoot.Timestamp, 0) 524 // This is to make sure kbfsRoot is built within 525 // maxAllowedMerkleGap from timeToCheck (which is the from the 526 // revoke signature). As mentioned in the large comment block 527 // above, since there's no other way to get a trustable time from 528 // this particular metadata update when we don't trust it yet, we 529 // use the "happens before K2" check below as a proxy, and make 530 // sure K2 is within the gap. 531 err = md.checkMerkleTimes( 532 ctx, latestRootTime, kbfsRoot, timeToCheck, 533 // Check the gap from the reverse direction, to make sure the 534 // roots were made _after_ the revoke within the gap. 535 -maxAllowedMerkleGap) 536 if err != nil { 537 return err 538 } 539 } 540 } 541 542 md.vlog.CLogf( 543 ctx, libkb.VLog1, 544 "Next KBFS merkle root is %d, included in global merkle root seqno=%d", 545 kbfsRoot.SeqNo, rootSeqno) 546 547 // Decode (and possibly decrypt) the leaf node, so we can see what 548 // the given MD revision number was for the MD that followed the 549 // revoke. 550 leaf, err := md.makeMerkleLeaf( 551 ctx, irmd.ReadOnlyRootMetadata, kbfsRoot, 552 merkleNodes[len(merkleNodes)-1]) 553 if err != nil { 554 return err 555 } 556 557 // If the given revision comes after the merkle leaf revision, 558 // then don't verify it. 559 // 560 // In the context of the large comment at the beginning of this method, 561 // this is to check a write happens before K2. 562 if irmd.Revision() > leaf.Revision { 563 return MDWrittenAfterRevokeError{ 564 irmd.TlfID(), irmd.Revision(), leaf.Revision, verifyingKey} 565 } else if irmd.Revision() == leaf.Revision { 566 return nil 567 } 568 569 // Otherwise it's valid, as long as there's a valid chain of MD 570 // revisions between the two. First, see which chain we've 571 // already validated, and if this revision falls in that chain, 572 // we're done. Otherwise, just fetch the part of the chain we 573 // haven't validated yet. 574 newChainEnd := md.startOfValidatedChainForLeaf(irmd.TlfID(), leaf.Revision) 575 if newChainEnd <= irmd.Revision() { 576 return nil 577 } 578 579 // By using `ctx`, we'll avoid infinite loops in the 580 // writer-key-checking code by skipping revoked key verification. 581 // This is ok, because we only care about the hash chain for the 582 // purposes of verifying `irmd`. 583 md.vlog.CLogf( 584 ctx, libkb.VLog1, "Validating MD chain for TLF %s between %d and %d", 585 irmd.TlfID(), irmd.Revision()+1, newChainEnd) 586 chain, err := getMergedMDUpdatesWithEnd( 587 ctx, md.config, irmd.TlfID(), irmd.Revision()+1, newChainEnd, nil) 588 if err != nil { 589 return err 590 } 591 if len(chain) == 0 { 592 return errors.Errorf("Unexpectedly found no revisions "+ 593 "after %d, even though the merkle tree includes revision %d", 594 irmd.Revision(), leaf.Revision) 595 } 596 597 err = irmd.CheckValidSuccessor(irmd.mdID, chain[0].ReadOnlyRootMetadata) 598 if err != nil { 599 return err 600 } 601 602 // Cache this verified chain for later use. 603 md.lock.Lock() 604 defer md.lock.Unlock() 605 revs, ok := md.leafChainsValidated[irmd.TlfID()] 606 if !ok { 607 revs = make(map[kbfsmd.Revision]kbfsmd.Revision) 608 md.leafChainsValidated[irmd.TlfID()] = revs 609 } 610 revs[leaf.Revision] = irmd.Revision() 611 return nil 612 } 613 614 func (md *MDOpsStandard) verifyKey( 615 ctx context.Context, rmds *RootMetadataSigned, 616 uid keybase1.UID, verifyingKey kbfscrypto.VerifyingKey, 617 irmd ImmutableRootMetadata) (cacheable bool, err error) { 618 err = md.config.KBPKI().HasVerifyingKey( 619 ctx, uid, verifyingKey, rmds.untrustedServerTimestamp, 620 md.config.OfflineAvailabilityForID(irmd.TlfID())) 621 var info idutil.RevokedKeyInfo 622 switch e := errors.Cause(err).(type) { 623 case nil: 624 return true, nil 625 case RevokedDeviceVerificationError: 626 if ctx.Value(ctxMDOpsSkipKeyVerification) != nil { 627 md.vlog.CLogf( 628 ctx, libkb.VLog1, 629 "Skipping revoked key verification due to recursion") 630 return false, nil 631 } 632 if e.info.MerkleRoot.Seqno <= 0 { 633 md.log.CDebugf(ctx, "Can't verify an MD written by a revoked "+ 634 "device if there's no valid root seqno to check: %+v", e) 635 return true, nil 636 } 637 638 info = e.info 639 // Fall through to check via the merkle tree. 640 default: 641 return false, err 642 } 643 644 md.vlog.CLogf( 645 ctx, libkb.VLog1, "Revision %d for %s was signed by a device that was "+ 646 "revoked at time=%d,root=%d; checking via Merkle", 647 irmd.Revision(), irmd.TlfID(), info.Time, info.MerkleRoot.Seqno) 648 649 err = md.checkRevisionCameBeforeMerkle( 650 ctx, rmds, verifyingKey, irmd, info.MerkleRoot, 651 keybase1.FromTime(info.Time)) 652 if err != nil { 653 return false, err 654 } 655 return true, nil 656 } 657 658 func (md *MDOpsStandard) verifyWriterKey(ctx context.Context, 659 rmds *RootMetadataSigned, irmd ImmutableRootMetadata, handle *tlfhandle.Handle, 660 getRangeLock *sync.Mutex) error { 661 if !rmds.MD.IsWriterMetadataCopiedSet() { 662 // Skip verifying the writer key if it's the same as the 663 // overall signer's key (which must be verified elsewhere). 664 if rmds.GetWriterMetadataSigInfo().VerifyingKey == 665 rmds.SigInfo.VerifyingKey { 666 return nil 667 } 668 669 _, err := md.verifyKey( 670 ctx, rmds, rmds.MD.LastModifyingWriter(), 671 rmds.GetWriterMetadataSigInfo().VerifyingKey, irmd) 672 if err != nil { 673 return md.convertVerifyingKeyError(ctx, rmds, handle, err) 674 } 675 return nil 676 } 677 678 // The writer metadata can be copied only for rekeys or 679 // finalizations, neither of which should happen while 680 // unmerged. 681 if rmds.MD.MergedStatus() != kbfsmd.Merged { 682 return errors.Errorf("Revision %d for %s has a copied writer "+ 683 "metadata, but is unexpectedly not merged", 684 rmds.MD.RevisionNumber(), rmds.MD.TlfID()) 685 } 686 687 if getRangeLock != nil { 688 // If there are multiple goroutines, we don't want to risk 689 // several concurrent requests to the MD server, just in case 690 // there are several revisions with copied writer MD in this 691 // range. 692 // 693 // TODO: bugs could result in thousands (or more) copied MD 694 // updates in a row (i.e., too many to fit in the cache). We 695 // could do something more sophisticated here where once one 696 // goroutine finds the copied MD, it stores it somewhere so 697 // the other goroutines don't have to also search through all 698 // the same MD updates (which may have been evicted from the 699 // cache in the meantime). Also, maybe copied writer MDs 700 // should include the original revision number so we don't 701 // have to search like this. 702 getRangeLock.Lock() 703 defer getRangeLock.Unlock() 704 } 705 706 // The server timestamp on rmds does not reflect when the 707 // writer MD was actually signed, since it was copied from a 708 // previous revision. Search backwards for the most recent 709 // uncopied writer MD to get the right timestamp. 710 for prevRev := rmds.MD.RevisionNumber() - 1; prevRev >= kbfsmd.RevisionInitial; prevRev-- { 711 // Recursively call into MDOps. Note that in the case where 712 // we were already fetching a range of MDs, this could do 713 // extra work by downloading the same MDs twice (for those 714 // that aren't yet in the cache). That should be so rare that 715 // it's not worth optimizing. 716 rmd, err := GetSingleMD(ctx, md.config, rmds.MD.TlfID(), 717 rmds.MD.BID(), prevRev, rmds.MD.MergedStatus(), nil) 718 if err != nil { 719 return err 720 } 721 722 if !rmd.IsWriterMetadataCopiedSet() { 723 // We want to compare the writer signature of 724 // rmds with that of prevMDs[i]. However, we've 725 // already dropped prevMDs[i]'s writer 726 // signature. We can just verify prevMDs[i]'s 727 // writer metadata with rmds's signature, 728 // though. 729 buf, err := rmd.GetSerializedWriterMetadata(md.config.Codec()) 730 if err != nil { 731 return err 732 } 733 734 err = kbfscrypto.Verify( 735 buf, rmds.GetWriterMetadataSigInfo()) 736 if err != nil { 737 return errors.Errorf("Could not verify "+ 738 "uncopied writer metadata "+ 739 "from revision %d of folder "+ 740 "%s with signature from "+ 741 "revision %d: %v", 742 rmd.Revision(), 743 rmds.MD.TlfID(), 744 rmds.MD.RevisionNumber(), err) 745 } 746 747 // The fact the fact that we were able to process this 748 // MD correctly means that we already verified its key 749 // at the correct timestamp, so we're good. 750 return nil 751 } 752 } 753 return errors.Errorf( 754 "Couldn't find uncopied MD previous to "+ 755 "revision %d of folder %s for checking the writer "+ 756 "timestamp", rmds.MD.RevisionNumber(), rmds.MD.TlfID()) 757 } 758 759 type merkleBasedTeamChecker struct { 760 teamMembershipChecker 761 md *MDOpsStandard 762 rmds *RootMetadataSigned 763 irmd ImmutableRootMetadata 764 notCacheable bool 765 } 766 767 func (mbtc merkleBasedTeamChecker) IsTeamWriter( 768 ctx context.Context, tid keybase1.TeamID, uid keybase1.UID, 769 verifyingKey kbfscrypto.VerifyingKey, 770 offline keybase1.OfflineAvailability) (bool, error) { 771 isCurrentWriter, err := mbtc.teamMembershipChecker.IsTeamWriter( 772 ctx, tid, uid, verifyingKey, offline) 773 if err != nil { 774 return false, err 775 } 776 if isCurrentWriter { 777 return true, nil 778 } 779 780 if ctx.Value(ctxMDOpsSkipKeyVerification) != nil { 781 // Don't cache this fake verification. 782 mbtc.notCacheable = true 783 mbtc.md.vlog.CLogf( 784 ctx, libkb.VLog1, 785 "Skipping old team writership verification due to recursion") 786 return true, nil 787 } 788 789 // The user is not currently a writer of the team, but maybe they 790 // were at the time this MD was written. Find out the global 791 // merkle root where they were no longer a writer, and make sure 792 // this revision came before that. 793 mbtc.md.vlog.CLogf( 794 ctx, libkb.VLog1, "User %s is no longer a writer of team %s; "+ 795 "checking merkle trees to verify they were a writer at the time the "+ 796 "MD was written.", uid, tid) 797 root, err := mbtc.teamMembershipChecker.NoLongerTeamWriter( 798 ctx, tid, mbtc.irmd.TlfID().Type(), uid, verifyingKey, offline) 799 switch e := errors.Cause(err).(type) { 800 case nil: 801 // TODO(CORE-8199): pass in the time for the writer downgrade. 802 err = mbtc.md.checkRevisionCameBeforeMerkle( 803 ctx, mbtc.rmds, verifyingKey, mbtc.irmd, root, time.Time{}) 804 if err != nil { 805 return false, err 806 } 807 case libkb.MerkleClientError: 808 if e.IsOldTree() { 809 mbtc.md.vlog.CLogf( 810 ctx, libkb.VLog1, "Merkle root is too old for checking "+ 811 "the revoked key: %+v", err) 812 } else { 813 return false, err 814 } 815 default: 816 return false, err 817 } 818 819 return true, nil 820 } 821 822 func (mbtc merkleBasedTeamChecker) IsTeamReader( 823 ctx context.Context, tid keybase1.TeamID, uid keybase1.UID, 824 offline keybase1.OfflineAvailability) ( 825 bool, error) { 826 if mbtc.irmd.TlfID().Type() == tlf.Public { 827 return true, nil 828 } 829 830 isCurrentReader, err := mbtc.teamMembershipChecker.IsTeamReader( 831 ctx, tid, uid, offline) 832 if err != nil { 833 return false, err 834 } 835 if isCurrentReader { 836 return true, nil 837 } 838 839 // We don't yet have a way to check for past readership based on 840 // the Merkle tree, so for now return true. This isn't too bad, 841 // since this is only called for checking the last modifying user 842 // of an update (the last modifying _writer_ is tested with the 843 // above function). TODO: fix this once historic team readership 844 // is available in the service. 845 mbtc.md.vlog.CLogf( 846 ctx, libkb.VLog1, 847 "Faking old readership for user %s in team %s", uid, tid) 848 return true, nil 849 } 850 851 // processMetadata converts the given rmds to an 852 // ImmutableRootMetadata. After this function is called, rmds 853 // shouldn't be used. 854 func (md *MDOpsStandard) processMetadata(ctx context.Context, 855 handle *tlfhandle.Handle, rmds *RootMetadataSigned, extra kbfsmd.ExtraMetadata, 856 getRangeLock *sync.Mutex) (ImmutableRootMetadata, error) { 857 // First, construct the ImmutableRootMetadata object, even before 858 // we validate the writer or the keys, because the irmd will be 859 // used in that process to check for valid successors. 860 861 // Get the UID unless this is a public tlf - then proceed with empty uid. 862 var uid keybase1.UID 863 if handle.Type() != tlf.Public { 864 session, err := md.config.KBPKI().GetCurrentSession(ctx) 865 if err != nil { 866 return ImmutableRootMetadata{}, err 867 } 868 uid = session.UID 869 } 870 871 // TODO: Avoid having to do this type assertion. 872 brmd, ok := rmds.MD.(kbfsmd.MutableRootMetadata) 873 if !ok { 874 return ImmutableRootMetadata{}, kbfsmd.MutableRootMetadataNoImplError{} 875 } 876 877 rmd := makeRootMetadata(brmd, extra, handle) 878 // Try to decrypt using the keys available in this md. If that 879 // doesn't work, a future MD may contain more keys and will be 880 // tried later. 881 pmd, err := decryptMDPrivateData( 882 ctx, md.config.Codec(), md.config.Crypto(), 883 md.config.BlockCache(), md.config.BlockOps(), 884 md.config.KeyManager(), md.config.KBPKI(), md.config, md.config.Mode(), 885 uid, rmd.GetSerializedPrivateMetadata(), rmd, rmd, md.log) 886 if err != nil { 887 return ImmutableRootMetadata{}, err 888 } 889 rmd.data = pmd 890 891 mdID, err := kbfsmd.MakeID(md.config.Codec(), rmd.bareMd) 892 if err != nil { 893 return ImmutableRootMetadata{}, err 894 } 895 896 localTimestamp := rmds.untrustedServerTimestamp 897 mdserv, err := md.mdserver(ctx) 898 if err != nil { 899 return ImmutableRootMetadata{}, err 900 } 901 if offset, ok := mdserv.OffsetFromServerTime(); ok { 902 localTimestamp = localTimestamp.Add(offset) 903 } 904 905 key := rmds.GetWriterMetadataSigInfo().VerifyingKey 906 irmd := MakeImmutableRootMetadata(rmd, key, mdID, localTimestamp, true) 907 908 // Next, verify validity and signatures. Use a checker that can 909 // check for writership in the past, using the merkle tree. 910 checker := merkleBasedTeamChecker{md.config.KBPKI(), md, rmds, irmd, false} 911 err = rmds.IsValidAndSigned( 912 ctx, md.config.Codec(), checker, extra, 913 md.config.OfflineAvailabilityForID(handle.TlfID())) 914 if err != nil { 915 return ImmutableRootMetadata{}, MDMismatchError{ 916 rmds.MD.RevisionNumber(), handle.GetCanonicalPath(), 917 rmds.MD.TlfID(), err, 918 } 919 } 920 921 // Then, verify the verifying keys. We do this after decrypting 922 // the MD and making the ImmutableRootMetadata, since we may need 923 // access to the private metadata when checking the merkle roots, 924 // and we also need access to the `mdID`. 925 if err := md.verifyWriterKey( 926 ctx, rmds, irmd, handle, getRangeLock); err != nil { 927 return ImmutableRootMetadata{}, err 928 } 929 930 cacheable, err := md.verifyKey( 931 ctx, rmds, rmds.MD.GetLastModifyingUser(), rmds.SigInfo.VerifyingKey, 932 irmd) 933 if err != nil { 934 return ImmutableRootMetadata{}, md.convertVerifyingKeyError( 935 ctx, rmds, handle, err) 936 } 937 938 // Make sure the caller doesn't use rmds anymore. 939 *rmds = RootMetadataSigned{} 940 941 if cacheable && !checker.notCacheable { 942 err = md.config.MDCache().Put(irmd) 943 if err != nil { 944 return ImmutableRootMetadata{}, err 945 } 946 } 947 return irmd, nil 948 } 949 950 func (md *MDOpsStandard) getForHandle(ctx context.Context, handle *tlfhandle.Handle, 951 mStatus kbfsmd.MergeStatus, lockBeforeGet *keybase1.LockID) ( 952 id tlf.ID, rmd ImmutableRootMetadata, err error) { 953 // If we already know the tlf ID, we shouldn't be calling this 954 // function. 955 if handle.TlfID() != tlf.NullID { 956 return tlf.ID{}, ImmutableRootMetadata{}, errors.Errorf( 957 "GetForHandle called for %s with non-nil TLF ID %s", 958 handle.GetCanonicalPath(), handle.TlfID()) 959 } 960 961 // Check for handle readership, to give a nice error early. 962 if handle.Type() == tlf.Private && !handle.IsBackedByTeam() { 963 session, err := md.config.KBPKI().GetCurrentSession(ctx) 964 if err != nil { 965 return tlf.ID{}, ImmutableRootMetadata{}, err 966 } 967 968 if !handle.IsReader(session.UID) { 969 return tlf.ID{}, ImmutableRootMetadata{}, 970 tlfhandle.NewReadAccessError( 971 handle, session.Name, handle.GetCanonicalPath()) 972 } 973 } 974 975 md.log.CDebugf( 976 ctx, "GetForHandle: %s %s", handle.GetCanonicalPath(), mStatus) 977 defer func() { 978 // Temporary debugging for KBFS-1921. TODO: remove. 979 switch { 980 case err != nil: 981 md.log.CDebugf(ctx, "GetForHandle done with err=%+v", err) 982 case rmd != (ImmutableRootMetadata{}): 983 md.log.CDebugf(ctx, "GetForHandle done, id=%s, revision=%d, "+ 984 "mStatus=%s", id, rmd.Revision(), rmd.MergedStatus()) 985 default: 986 md.log.CDebugf( 987 ctx, "GetForHandle done, id=%s, no %s MD revisions yet", id, 988 mStatus) 989 } 990 }() 991 992 mdserv, err := md.mdserver(ctx) 993 if err != nil { 994 return tlf.ID{}, ImmutableRootMetadata{}, err 995 } 996 bh, err := handle.ToBareHandle() 997 if err != nil { 998 return tlf.ID{}, ImmutableRootMetadata{}, err 999 } 1000 if handle.IsLocalConflict() { 1001 md.log.CDebugf(ctx, "Stripping out local conflict info from %s "+ 1002 "before fetching the ID", handle.GetCanonicalPath()) 1003 bh.ConflictInfo = nil 1004 } 1005 1006 id, rmds, err := mdserv.GetForHandle(ctx, bh, mStatus, lockBeforeGet) 1007 if err != nil { 1008 return tlf.ID{}, ImmutableRootMetadata{}, err 1009 } 1010 1011 if rmds == nil { 1012 if mStatus == kbfsmd.Unmerged { 1013 // The caller ignores the id argument for 1014 // mStatus == kbfsmd.Unmerged. 1015 return tlf.ID{}, ImmutableRootMetadata{}, nil 1016 } 1017 return id, ImmutableRootMetadata{}, nil 1018 } 1019 1020 extra, err := md.getExtraMD(ctx, rmds.MD) 1021 if err != nil { 1022 return tlf.ID{}, ImmutableRootMetadata{}, err 1023 } 1024 1025 bareMdHandle, err := rmds.MD.MakeBareTlfHandle(extra) 1026 if err != nil { 1027 return tlf.ID{}, ImmutableRootMetadata{}, err 1028 } 1029 1030 mdHandle, err := tlfhandle.MakeHandle( 1031 ctx, bareMdHandle, id.Type(), md.config.KBPKI(), md.config.KBPKI(), nil, 1032 md.config.OfflineAvailabilityForID(id)) 1033 if err != nil { 1034 return tlf.ID{}, ImmutableRootMetadata{}, err 1035 } 1036 1037 // Check for mutual handle resolution. 1038 if err := mdHandle.MutuallyResolvesTo(ctx, md.config.Codec(), 1039 md.config.KBPKI(), nil, md.config, *handle, rmds.MD.RevisionNumber(), 1040 rmds.MD.TlfID(), md.log); err != nil { 1041 return tlf.ID{}, ImmutableRootMetadata{}, err 1042 } 1043 // Set the ID after checking the resolve, because `handle` doesn't 1044 // have the TLF ID set yet. 1045 mdHandle.SetTlfID(id) 1046 1047 // TODO: For now, use the mdHandle that came with rmds for 1048 // consistency. In the future, we'd want to eventually notify 1049 // the upper layers of the new name, either directly, or 1050 // through a rekey. 1051 rmd, err = md.processMetadata(ctx, mdHandle, rmds, extra, nil) 1052 if err != nil { 1053 return tlf.ID{}, ImmutableRootMetadata{}, err 1054 } 1055 1056 return id, rmd, nil 1057 } 1058 1059 // GetIDForHandle implements the MDOps interface for MDOpsStandard. 1060 func (md *MDOpsStandard) GetIDForHandle( 1061 ctx context.Context, handle *tlfhandle.Handle) (id tlf.ID, err error) { 1062 mdcache := md.config.MDCache() 1063 id, err = mdcache.GetIDForHandle(handle) 1064 switch errors.Cause(err).(type) { 1065 case NoSuchTlfIDError: 1066 // Do the server-based lookup below. 1067 case nil: 1068 return id, nil 1069 default: 1070 return tlf.NullID, err 1071 } 1072 id, _, err = md.getForHandle(ctx, handle, kbfsmd.Merged, nil) 1073 switch errors.Cause(err).(type) { 1074 case kbfsmd.ServerErrorClassicTLFDoesNotExist: 1075 // The server thinks we should create an implicit team for this TLF. 1076 return tlf.NullID, nil 1077 case nil: 1078 default: 1079 return tlf.NullID, err 1080 } 1081 if !handle.IsLocalConflict() { 1082 err = mdcache.PutIDForHandle(handle, id) 1083 if err != nil { 1084 return tlf.NullID, err 1085 } 1086 } 1087 return id, nil 1088 } 1089 1090 func (md *MDOpsStandard) processMetadataWithID(ctx context.Context, 1091 id tlf.ID, bid kbfsmd.BranchID, handle *tlfhandle.Handle, rmds *RootMetadataSigned, 1092 extra kbfsmd.ExtraMetadata, getRangeLock *sync.Mutex) (ImmutableRootMetadata, error) { 1093 // Make sure the signed-over ID matches 1094 if id != rmds.MD.TlfID() { 1095 return ImmutableRootMetadata{}, MDMismatchError{ 1096 rmds.MD.RevisionNumber(), id.String(), rmds.MD.TlfID(), 1097 errors.Errorf("MD contained unexpected folder id %s, expected %s", 1098 rmds.MD.TlfID().String(), id.String()), 1099 } 1100 } 1101 // Make sure the signed-over branch ID matches 1102 if bid != kbfsmd.NullBranchID && bid != rmds.MD.BID() { 1103 return ImmutableRootMetadata{}, MDMismatchError{ 1104 rmds.MD.RevisionNumber(), id.String(), rmds.MD.TlfID(), 1105 errors.Errorf("MD contained unexpected branch id %s, expected %s, "+ 1106 "folder id %s", rmds.MD.BID().String(), bid.String(), id.String()), 1107 } 1108 } 1109 1110 return md.processMetadata(ctx, handle, rmds, extra, getRangeLock) 1111 } 1112 1113 func (md *MDOpsStandard) processSignedMD( 1114 ctx context.Context, id tlf.ID, bid kbfsmd.BranchID, 1115 rmds *RootMetadataSigned) (ImmutableRootMetadata, error) { 1116 extra, err := md.getExtraMD(ctx, rmds.MD) 1117 if err != nil { 1118 return ImmutableRootMetadata{}, err 1119 } 1120 bareHandle, err := rmds.MD.MakeBareTlfHandle(extra) 1121 if err != nil { 1122 return ImmutableRootMetadata{}, err 1123 } 1124 handle, err := tlfhandle.MakeHandleWithTlfID( 1125 ctx, bareHandle, rmds.MD.TlfID().Type(), md.config.KBPKI(), 1126 md.config.KBPKI(), id, md.config.OfflineAvailabilityForID(id)) 1127 if err != nil { 1128 return ImmutableRootMetadata{}, err 1129 } 1130 rmd, err := md.processMetadataWithID(ctx, id, bid, handle, rmds, extra, nil) 1131 if err != nil { 1132 return ImmutableRootMetadata{}, err 1133 } 1134 return rmd, nil 1135 } 1136 1137 func (md *MDOpsStandard) getForTLF(ctx context.Context, id tlf.ID, 1138 bid kbfsmd.BranchID, mStatus kbfsmd.MergeStatus, lockBeforeGet *keybase1.LockID) ( 1139 ImmutableRootMetadata, error) { 1140 mdserv, err := md.mdserver(ctx) 1141 if err != nil { 1142 return ImmutableRootMetadata{}, err 1143 } 1144 rmds, err := mdserv.GetForTLF(ctx, id, bid, mStatus, lockBeforeGet) 1145 if err != nil { 1146 return ImmutableRootMetadata{}, err 1147 } 1148 if rmds == nil { 1149 // Possible if mStatus is kbfsmd.Unmerged 1150 return ImmutableRootMetadata{}, nil 1151 } 1152 return md.processSignedMD(ctx, id, bid, rmds) 1153 } 1154 1155 // GetForTLF implements the MDOps interface for MDOpsStandard. 1156 func (md *MDOpsStandard) GetForTLF( 1157 ctx context.Context, id tlf.ID, lockBeforeGet *keybase1.LockID) ( 1158 ImmutableRootMetadata, error) { 1159 return md.getForTLF(ctx, id, kbfsmd.NullBranchID, kbfsmd.Merged, lockBeforeGet) 1160 } 1161 1162 // GetForTLFByTime implements the MDOps interface for MDOpsStandard. 1163 func (md *MDOpsStandard) GetForTLFByTime( 1164 ctx context.Context, id tlf.ID, serverTime time.Time) ( 1165 irmd ImmutableRootMetadata, err error) { 1166 md.log.CDebugf(ctx, "GetForTLFByTime %s %s", id, serverTime) 1167 defer func() { 1168 if err == nil { 1169 md.log.CDebugf(ctx, "GetForTLFByTime %s %s done: %d", 1170 id, serverTime, irmd.Revision()) 1171 } else { 1172 md.log.CDebugf(ctx, "GetForTLFByTime %s %s done: %+v", 1173 id, serverTime, err) 1174 } 1175 }() 1176 mdserv, err := md.mdserver(ctx) 1177 if err != nil { 1178 return ImmutableRootMetadata{}, err 1179 } 1180 rmds, err := mdserv.GetForTLFByTime(ctx, id, serverTime) 1181 if err != nil { 1182 return ImmutableRootMetadata{}, err 1183 } 1184 1185 return md.processSignedMD(ctx, id, kbfsmd.NullBranchID, rmds) 1186 } 1187 1188 // GetUnmergedForTLF implements the MDOps interface for MDOpsStandard. 1189 func (md *MDOpsStandard) GetUnmergedForTLF( 1190 ctx context.Context, id tlf.ID, bid kbfsmd.BranchID) ( 1191 ImmutableRootMetadata, error) { 1192 return md.getForTLF(ctx, id, bid, kbfsmd.Unmerged, nil) 1193 } 1194 1195 func (md *MDOpsStandard) processRange(ctx context.Context, id tlf.ID, 1196 bid kbfsmd.BranchID, rmdses []*RootMetadataSigned) ( 1197 []ImmutableRootMetadata, error) { 1198 if len(rmdses) == 0 { 1199 return nil, nil 1200 } 1201 1202 eg, groupCtx := errgroup.WithContext(ctx) 1203 1204 // Parallelize the MD decryption, because it could involve 1205 // fetching blocks to get unembedded block changes. 1206 rmdsChan := make(chan *RootMetadataSigned, len(rmdses)) 1207 irmdChan := make(chan ImmutableRootMetadata, len(rmdses)) 1208 var getRangeLock sync.Mutex 1209 worker := func() error { 1210 for rmds := range rmdsChan { 1211 extra, err := md.getExtraMD(groupCtx, rmds.MD) 1212 if err != nil { 1213 return err 1214 } 1215 bareHandle, err := rmds.MD.MakeBareTlfHandle(extra) 1216 if err != nil { 1217 return err 1218 } 1219 handle, err := tlfhandle.MakeHandleWithTlfID( 1220 groupCtx, bareHandle, rmds.MD.TlfID().Type(), md.config.KBPKI(), 1221 md.config.KBPKI(), id, md.config.OfflineAvailabilityForID(id)) 1222 if err != nil { 1223 return err 1224 } 1225 irmd, err := md.processMetadataWithID(groupCtx, id, bid, 1226 handle, rmds, extra, &getRangeLock) 1227 if err != nil { 1228 return err 1229 } 1230 irmdChan <- irmd 1231 } 1232 return nil 1233 } 1234 1235 numWorkers := len(rmdses) 1236 if numWorkers > maxMDsAtATime { 1237 numWorkers = maxMDsAtATime 1238 } 1239 for i := 0; i < numWorkers; i++ { 1240 eg.Go(worker) 1241 } 1242 1243 // Do this first, since processMetadataWithID consumes its 1244 // rmds argument. 1245 startRev := rmdses[0].MD.RevisionNumber() 1246 rmdsCount := len(rmdses) 1247 1248 for _, rmds := range rmdses { 1249 rmdsChan <- rmds 1250 } 1251 close(rmdsChan) 1252 err := eg.Wait() 1253 if err != nil { 1254 return nil, err 1255 } 1256 close(irmdChan) 1257 1258 // Sort into slice based on revision. 1259 irmds := make([]ImmutableRootMetadata, rmdsCount) 1260 numExpected := kbfsmd.Revision(len(irmds)) 1261 for irmd := range irmdChan { 1262 i := irmd.Revision() - startRev 1263 if i < 0 || i >= numExpected { 1264 return nil, errors.Errorf("Unexpected revision %d; expected "+ 1265 "something between %d and %d inclusive", irmd.Revision(), 1266 startRev, startRev+numExpected-1) 1267 } else if irmds[i] != (ImmutableRootMetadata{}) { 1268 return nil, errors.Errorf("Got revision %d twice", irmd.Revision()) 1269 } 1270 irmds[i] = irmd 1271 } 1272 1273 // Now that we have all the immutable RootMetadatas, verify that 1274 // the given MD objects form a valid sequence. 1275 var prevIRMD ImmutableRootMetadata 1276 for _, irmd := range irmds { 1277 if prevIRMD != (ImmutableRootMetadata{}) { 1278 err = prevIRMD.CheckValidSuccessor( 1279 prevIRMD.mdID, irmd.ReadOnlyRootMetadata) 1280 if err != nil { 1281 return nil, MDMismatchError{ 1282 prevIRMD.Revision(), 1283 irmd.GetTlfHandle().GetCanonicalPath(), 1284 prevIRMD.TlfID(), err, 1285 } 1286 } 1287 } 1288 prevIRMD = irmd 1289 } 1290 1291 // TODO: in the case where lastRoot == MdID{}, should we verify 1292 // that the starting PrevRoot points back to something that's 1293 // actually a valid part of this history? If the MD signature is 1294 // indeed valid, this probably isn't a huge deal, but it may let 1295 // the server rollback or truncate unmerged history... 1296 1297 return irmds, nil 1298 } 1299 1300 func (md *MDOpsStandard) getRange(ctx context.Context, id tlf.ID, 1301 bid kbfsmd.BranchID, mStatus kbfsmd.MergeStatus, start, stop kbfsmd.Revision, 1302 lockBeforeGet *keybase1.LockID) ([]ImmutableRootMetadata, error) { 1303 mdserv, err := md.mdserver(ctx) 1304 if err != nil { 1305 return nil, err 1306 } 1307 rmds, err := mdserv.GetRange( 1308 ctx, id, bid, mStatus, start, stop, lockBeforeGet) 1309 if err != nil { 1310 return nil, err 1311 } 1312 rmd, err := md.processRange(ctx, id, bid, rmds) 1313 if err != nil { 1314 return nil, err 1315 } 1316 return rmd, nil 1317 } 1318 1319 // GetRange implements the MDOps interface for MDOpsStandard. 1320 func (md *MDOpsStandard) GetRange(ctx context.Context, id tlf.ID, 1321 start, stop kbfsmd.Revision, lockBeforeGet *keybase1.LockID) ( 1322 []ImmutableRootMetadata, error) { 1323 return md.getRange( 1324 ctx, id, kbfsmd.NullBranchID, kbfsmd.Merged, start, stop, lockBeforeGet) 1325 } 1326 1327 // GetUnmergedRange implements the MDOps interface for MDOpsStandard. 1328 func (md *MDOpsStandard) GetUnmergedRange(ctx context.Context, id tlf.ID, 1329 bid kbfsmd.BranchID, start, stop kbfsmd.Revision) ( 1330 []ImmutableRootMetadata, error) { 1331 return md.getRange(ctx, id, bid, kbfsmd.Unmerged, start, stop, nil) 1332 } 1333 1334 func (md *MDOpsStandard) put(ctx context.Context, rmd *RootMetadata, 1335 verifyingKey kbfscrypto.VerifyingKey, lockContext *keybase1.LockContext, 1336 priority keybase1.MDPriority, bps data.BlockPutState) ( 1337 ImmutableRootMetadata, error) { 1338 session, err := md.config.KBPKI().GetCurrentSession(ctx) 1339 if err != nil { 1340 return ImmutableRootMetadata{}, err 1341 } 1342 1343 // Ensure that the block changes are properly unembedded. 1344 if !rmd.IsWriterMetadataCopiedSet() && 1345 rmd.data.Changes.Info.BlockPointer == data.ZeroPtr && 1346 !md.config.BlockSplitter().ShouldEmbedData( 1347 rmd.data.Changes.SizeEstimate()) { 1348 return ImmutableRootMetadata{}, 1349 errors.New("MD has embedded block changes, but shouldn't") 1350 } 1351 1352 err = encryptMDPrivateData( 1353 ctx, md.config.Codec(), md.config.Crypto(), 1354 md.config.Crypto(), md.config.KeyManager(), session.UID, rmd) 1355 if err != nil { 1356 return ImmutableRootMetadata{}, err 1357 } 1358 1359 rmds, err := SignBareRootMetadata( 1360 ctx, md.config.Codec(), md.config.Crypto(), md.config.Crypto(), 1361 rmd.bareMd, time.Time{}) 1362 if err != nil { 1363 return ImmutableRootMetadata{}, err 1364 } 1365 1366 mdserv, err := md.mdserver(ctx) 1367 if err != nil { 1368 return ImmutableRootMetadata{}, err 1369 } 1370 err = mdserv.Put(ctx, rmds, rmd.extra, lockContext, priority) 1371 if err != nil { 1372 return ImmutableRootMetadata{}, err 1373 } 1374 1375 mdID, err := kbfsmd.MakeID(md.config.Codec(), rmds.MD) 1376 if err != nil { 1377 return ImmutableRootMetadata{}, err 1378 } 1379 1380 rmd, err = rmd.loadCachedBlockChanges( 1381 ctx, bps, md.log, md.vlog, md.config.Codec()) 1382 if err != nil { 1383 return ImmutableRootMetadata{}, err 1384 } 1385 irmd := MakeImmutableRootMetadata( 1386 rmd, verifyingKey, mdID, md.config.Clock().Now(), true) 1387 // Revisions created locally should always override anything else 1388 // in the cache. 1389 err = md.config.MDCache().Replace(irmd, irmd.BID()) 1390 if err != nil { 1391 return ImmutableRootMetadata{}, err 1392 } 1393 md.log.CDebugf(ctx, "Put MD rev=%d id=%s", rmd.Revision(), mdID) 1394 1395 return irmd, nil 1396 } 1397 1398 // Put implements the MDOps interface for MDOpsStandard. 1399 func (md *MDOpsStandard) Put(ctx context.Context, rmd *RootMetadata, 1400 verifyingKey kbfscrypto.VerifyingKey, lockContext *keybase1.LockContext, 1401 priority keybase1.MDPriority, bps data.BlockPutState) ( 1402 ImmutableRootMetadata, error) { 1403 if rmd.MergedStatus() == kbfsmd.Unmerged { 1404 return ImmutableRootMetadata{}, UnexpectedUnmergedPutError{} 1405 } 1406 return md.put(ctx, rmd, verifyingKey, lockContext, priority, bps) 1407 } 1408 1409 // PutUnmerged implements the MDOps interface for MDOpsStandard. 1410 func (md *MDOpsStandard) PutUnmerged( 1411 ctx context.Context, rmd *RootMetadata, 1412 verifyingKey kbfscrypto.VerifyingKey, bps data.BlockPutState) ( 1413 ImmutableRootMetadata, error) { 1414 rmd.SetUnmerged() 1415 if rmd.BID() == kbfsmd.NullBranchID { 1416 // new branch ID 1417 bid, err := md.config.Crypto().MakeRandomBranchID() 1418 if err != nil { 1419 return ImmutableRootMetadata{}, err 1420 } 1421 rmd.SetBranchID(bid) 1422 } 1423 return md.put(ctx, rmd, verifyingKey, nil, keybase1.MDPriorityNormal, bps) 1424 } 1425 1426 // PruneBranch implements the MDOps interface for MDOpsStandard. 1427 func (md *MDOpsStandard) PruneBranch( 1428 ctx context.Context, id tlf.ID, bid kbfsmd.BranchID) error { 1429 mdserv, err := md.mdserver(ctx) 1430 if err != nil { 1431 return err 1432 } 1433 return mdserv.PruneBranch(ctx, id, bid) 1434 } 1435 1436 // ResolveBranch implements the MDOps interface for MDOpsStandard. 1437 func (md *MDOpsStandard) ResolveBranch( 1438 ctx context.Context, id tlf.ID, bid kbfsmd.BranchID, _ []kbfsblock.ID, 1439 rmd *RootMetadata, verifyingKey kbfscrypto.VerifyingKey, 1440 bps data.BlockPutState) (ImmutableRootMetadata, error) { 1441 // Put the MD first. 1442 irmd, err := md.Put( 1443 ctx, rmd, verifyingKey, nil, keybase1.MDPriorityNormal, bps) 1444 if err != nil { 1445 return ImmutableRootMetadata{}, err 1446 } 1447 1448 // Prune the branch ia the journal, if there is one. If the 1449 // client fails before this is completed, we'll need to check for 1450 // resolutions on the next restart (see KBFS-798). 1451 err = md.PruneBranch(ctx, id, bid) 1452 if err != nil { 1453 return ImmutableRootMetadata{}, err 1454 } 1455 return irmd, nil 1456 } 1457 1458 // GetLatestHandleForTLF implements the MDOps interface for MDOpsStandard. 1459 func (md *MDOpsStandard) GetLatestHandleForTLF(ctx context.Context, id tlf.ID) ( 1460 tlf.Handle, error) { 1461 mdserv, err := md.mdserver(ctx) 1462 if err != nil { 1463 return tlf.Handle{}, err 1464 } 1465 // TODO: Verify this mapping using a Merkle tree. 1466 return mdserv.GetLatestHandleForTLF(ctx, id) 1467 } 1468 1469 // ValidateLatestHandleNotFinal implements the MDOps interface for 1470 // MDOpsStandard. 1471 func (md *MDOpsStandard) ValidateLatestHandleNotFinal( 1472 ctx context.Context, h *tlfhandle.Handle) (bool, error) { 1473 if h.IsFinal() || h.TlfID() == tlf.NullID { 1474 return false, nil 1475 } 1476 1477 // First check the cache to avoid a costly RTT to the mdserver. 1478 // If the handle associated with the TLF has really become 1479 // finalized, then the cache entry should have been updated. 1480 mdcache := md.config.MDCache() 1481 id, err := mdcache.GetIDForHandle(h) 1482 switch errors.Cause(err).(type) { 1483 case NoSuchTlfIDError: 1484 // Do the server-based lookup below. 1485 case nil: 1486 return id == h.TlfID(), nil 1487 default: 1488 return false, err 1489 } 1490 1491 md.log.CDebugf(ctx, "Checking the latest handle for %s; "+ 1492 "curr handle is %s", h.TlfID(), h.GetCanonicalName()) 1493 latestHandle, err := md.GetLatestHandleForTLF(ctx, h.TlfID()) 1494 switch errors.Cause(err).(type) { 1495 case kbfsmd.ServerErrorUnauthorized: 1496 // The server sends this in the case that it doesn't know 1497 // about the TLF ID. If the server didn't have the mapping, 1498 // we're likely dealing with an implicit team TLF. Trust what 1499 // is in the sigchain in that case. (If the error happens 1500 // because we really looked up a TLF we are unauthorized for, 1501 // earlier calls to the server should have failed before we 1502 // even got access to the TLF ID.) 1503 md.log.CDebugf(ctx, 1504 "Assuming unauthorized error implies implicit team TLF: %+v", err) 1505 return true, nil 1506 case nil: 1507 if latestHandle.IsFinal() { 1508 md.log.CDebugf(ctx, 1509 "Latest handle is finalized, so ID is incorrect") 1510 return false, nil 1511 } 1512 err = mdcache.PutIDForHandle(h, h.TlfID()) 1513 if err != nil { 1514 return false, err 1515 } 1516 return true, nil 1517 default: 1518 return false, err 1519 } 1520 } 1521 1522 func (md *MDOpsStandard) getExtraMD(ctx context.Context, brmd kbfsmd.RootMetadata) ( 1523 extra kbfsmd.ExtraMetadata, err error) { 1524 wkbID, rkbID := brmd.GetTLFWriterKeyBundleID(), brmd.GetTLFReaderKeyBundleID() 1525 if (wkbID == kbfsmd.TLFWriterKeyBundleID{}) || (rkbID == kbfsmd.TLFReaderKeyBundleID{}) { 1526 // Pre-v3 metadata embed key bundles and as such won't set any IDs. 1527 return nil, nil 1528 } 1529 mdserv, err := md.mdserver(ctx) 1530 if err != nil { 1531 return nil, err 1532 } 1533 kbcache := md.config.KeyBundleCache() 1534 tlf := brmd.TlfID() 1535 // Check the cache. 1536 wkb, err2 := kbcache.GetTLFWriterKeyBundle(wkbID) 1537 if err2 != nil { 1538 md.log.CDebugf(ctx, "Error fetching writer key bundle %s from cache for TLF %s: %s", 1539 wkbID, tlf, err2) 1540 } 1541 rkb, err2 := kbcache.GetTLFReaderKeyBundle(rkbID) 1542 if err2 != nil { 1543 md.log.CDebugf(ctx, "Error fetching reader key bundle %s from cache for TLF %s: %s", 1544 rkbID, tlf, err2) 1545 } 1546 if wkb != nil && rkb != nil { 1547 return kbfsmd.NewExtraMetadataV3(*wkb, *rkb, false, false), nil 1548 } 1549 switch { 1550 case wkb != nil: 1551 // Don't need the writer bundle. 1552 _, rkb, err = mdserv.GetKeyBundles(ctx, tlf, kbfsmd.TLFWriterKeyBundleID{}, rkbID) 1553 case rkb != nil: 1554 // Don't need the reader bundle. 1555 wkb, _, err = mdserv.GetKeyBundles(ctx, tlf, wkbID, kbfsmd.TLFReaderKeyBundleID{}) 1556 default: 1557 // Need them both. 1558 wkb, rkb, err = mdserv.GetKeyBundles(ctx, tlf, wkbID, rkbID) 1559 } 1560 if err != nil { 1561 return nil, err 1562 } 1563 // Cache the results. 1564 kbcache.PutTLFWriterKeyBundle(wkbID, *wkb) 1565 kbcache.PutTLFReaderKeyBundle(rkbID, *rkb) 1566 return kbfsmd.NewExtraMetadataV3(*wkb, *rkb, false, false), nil 1567 }