Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(219)

Unified Diff: sync/engine/apply_control_data_updates.cc

Issue 10905191: [Sync] Add keystore migration conflict support. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | sync/engine/apply_control_data_updates_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sync/engine/apply_control_data_updates.cc
diff --git a/sync/engine/apply_control_data_updates.cc b/sync/engine/apply_control_data_updates.cc
index 7a52e8c36c58f5f6ec522e06aad5396a8b794b84..aa1454ee894fb336474c32fab97a5a835b171219 100644
--- a/sync/engine/apply_control_data_updates.cc
+++ b/sync/engine/apply_control_data_updates.cc
@@ -57,6 +57,8 @@ bool ApplyNigoriUpdates(syncable::WriteTransaction* trans,
return true;
}
+ // We apply the nigori update regardless of whether there's a conflict or
+ // not in order to preserve any new encrypted types or encryption keys.
const sync_pb::NigoriSpecifics& nigori =
nigori_node.Get(SERVER_SPECIFICS).nigori();
trans->directory()->GetNigoriHandler()->ApplyNigoriUpdate(nigori, trans);
@@ -83,45 +85,67 @@ bool ApplyNigoriUpdates(syncable::WriteTransaction* trans,
if (!nigori_node.Get(IS_UNSYNCED)) { // Update only.
UpdateLocalDataFromServerData(trans, &nigori_node);
} else { // Conflict.
- // Create a new set of specifics based on the server specifics (which
- // preserves their encryption keys).
- sync_pb::EntitySpecifics specifics = nigori_node.Get(SERVER_SPECIFICS);
- sync_pb::NigoriSpecifics* server_nigori = specifics.mutable_nigori();
- // Store the merged set of encrypted types.
- // (NigoriHandler::ApplyNigoriUpdate(..) will have merged the local types
- // already).
- trans->directory()->GetNigoriHandler()->UpdateNigoriFromEncryptedTypes(
- server_nigori,
- trans);
- // The cryptographer has the both the local and remote encryption keys
- // (added at NigoriHandler::ApplyNigoriUpdate(..) time).
- // If the cryptographer is ready, then it already merged both sets of keys
- // and we can store them back in. In that case, the remote key was already
- // part of the local keybag, so we preserve the local key as the default
- // (including whether it's an explicit key).
- // If the cryptographer is not ready, then the user will have to provide
- // the passphrase to decrypt the pending keys. When they do so, the
- // SetDecryptionPassphrase code will act based on whether the server
- // update has an explicit passphrase or not.
- // - If the server had an explicit passphrase, that explicit passphrase
- // will be preserved as the default encryption key.
- // - If the server did not have an explicit passphrase, we assume the
- // local passphrase is the most up to date and preserve the local
- // default encryption key marked as an implicit passphrase.
- // This works fine except for the case where we had locally set an
- // explicit passphrase. In that case the nigori node will have the default
- // key based on the local explicit passphassphrase, but will not have it
- // marked as explicit. To fix this we'd have to track whether we have a
- // explicit passphrase or not separate from the nigori, which would
- // introduce even more complexity, so we leave it up to the user to reset
- // that passphrase as an explicit one via settings. The goal here is to
- // ensure both sets of encryption keys are preserved.
+ const sync_pb::EntitySpecifics& server_specifics =
+ nigori_node.Get(SERVER_SPECIFICS);
+ const sync_pb::NigoriSpecifics& server_nigori = server_specifics.nigori();
+ const sync_pb::EntitySpecifics& local_specifics =
+ nigori_node.Get(SPECIFICS);
+ const sync_pb::NigoriSpecifics& local_nigori = local_specifics.nigori();
+
+ // We initialize the new nigori with the server state, and will override
+ // it as necessary below.
+ sync_pb::EntitySpecifics new_specifics = nigori_node.Get(SERVER_SPECIFICS);
+ sync_pb::NigoriSpecifics* new_nigori = new_specifics.mutable_nigori();
+
+ // If the cryptographer is not ready, another client set a new encryption
+ // passphrase. If we had migrated locally, we will re-migrate when the
+ // pending keys are provided. If we had set a new custom passphrase locally
+ // the user will have another chance to set a custom passphrase later
+ // (assuming they hadn't set a custom passphrase on the other client).
+ // Therefore, we only attempt to merge the nigori nodes if the cryptographer
+ // is ready.
+ // Note: we only update the encryption keybag if we're sure that we aren't
+ // invalidating the keystore_decryptor_token (i.e. we're either
+ // not migrated or we copying over all local state).
if (cryptographer->is_ready()) {
- cryptographer->GetKeys(server_nigori->mutable_encryption_keybag());
- server_nigori->set_keybag_is_frozen(
- nigori_node.Get(SPECIFICS).nigori().keybag_is_frozen());
+ if (local_nigori.has_passphrase_type() &&
+ server_nigori.has_passphrase_type()) {
+ // They're both migrated, preserve the local nigori if the passphrase
+ // type is more conservative.
+ if (server_nigori.passphrase_type() ==
+ sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE &&
+ local_nigori.passphrase_type() !=
+ sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE) {
+ DCHECK(local_nigori.passphrase_type() ==
+ sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE ||
+ local_nigori.passphrase_type() ==
+ sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
+ new_nigori->CopyFrom(local_nigori);
+ cryptographer->GetKeys(new_nigori->mutable_encryption_keybag());
+ }
+ } else if (!local_nigori.has_passphrase_type() &&
+ !server_nigori.has_passphrase_type()) {
+ // Set the explicit passphrase based on the local state. If the server
+ // had set an explict passphrase, we should have pending keys, so
+ // should not reach this code.
+ // Because neither side is migrated, we don't have to worry about the
+ // keystore decryptor token.
+ new_nigori->set_keybag_is_frozen(local_nigori.keybag_is_frozen());
+ cryptographer->GetKeys(new_nigori->mutable_encryption_keybag());
+ } else if (local_nigori.has_passphrase_type()) {
+ // Local is migrated but server is not. Copy over the local migrated
+ // data.
+ new_nigori->CopyFrom(local_nigori);
+ cryptographer->GetKeys(new_nigori->mutable_encryption_keybag());
+ } // else leave the new nigori with the server state.
}
- nigori_node.Put(SPECIFICS, specifics);
+
+ // Always update to the safest set of encrypted types.
+ trans->directory()->GetNigoriHandler()->UpdateNigoriFromEncryptedTypes(
+ new_nigori,
+ trans);
+
+ nigori_node.Put(SPECIFICS, new_specifics);
DVLOG(1) << "Resolving simple conflict, merging nigori nodes: "
<< nigori_node;
« no previous file with comments | « no previous file | sync/engine/apply_control_data_updates_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698