diff options
Diffstat (limited to 'chromium/sync/syncable/nigori_util.cc')
-rw-r--r-- | chromium/sync/syncable/nigori_util.cc | 322 |
1 files changed, 0 insertions, 322 deletions
diff --git a/chromium/sync/syncable/nigori_util.cc b/chromium/sync/syncable/nigori_util.cc deleted file mode 100644 index 107a68f233b..00000000000 --- a/chromium/sync/syncable/nigori_util.cc +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sync/syncable/nigori_util.h" - -#include <queue> -#include <string> -#include <vector> - -#include "base/json/json_writer.h" -#include "sync/syncable/directory.h" -#include "sync/syncable/entry.h" -#include "sync/syncable/nigori_handler.h" -#include "sync/syncable/mutable_entry.h" -#include "sync/syncable/syncable_util.h" -#include "sync/syncable/syncable_write_transaction.h" -#include "sync/util/cryptographer.h" - -namespace syncer { -namespace syncable { - -bool ProcessUnsyncedChangesForEncryption( - WriteTransaction* const trans) { - NigoriHandler* nigori_handler = trans->directory()->GetNigoriHandler(); - ModelTypeSet encrypted_types = nigori_handler->GetEncryptedTypes(trans); - Cryptographer* cryptographer = trans->directory()->GetCryptographer(trans); - DCHECK(cryptographer->is_ready()); - - // Get list of all datatypes with unsynced changes. It's possible that our - // local changes need to be encrypted if encryption for that datatype was - // just turned on (and vice versa). - // Note: we do not attempt to re-encrypt data with a new key here as key - // changes in this code path are likely due to consistency issues (we have - // to be updated to a key we already have, e.g. an old key). - std::vector<int64> handles; - GetUnsyncedEntries(trans, &handles); - for (size_t i = 0; i < handles.size(); ++i) { - MutableEntry entry(trans, GET_BY_HANDLE, handles[i]); - const sync_pb::EntitySpecifics& specifics = entry.GetSpecifics(); - // Ignore types that don't need encryption or entries that are already - // encrypted. - if (!SpecificsNeedsEncryption(encrypted_types, specifics)) - continue; - if (!UpdateEntryWithEncryption(trans, specifics, &entry)) - return false; - } - return true; -} - -bool VerifyUnsyncedChangesAreEncrypted( - BaseTransaction* const trans, - ModelTypeSet encrypted_types) { - std::vector<int64> handles; - GetUnsyncedEntries(trans, &handles); - for (size_t i = 0; i < handles.size(); ++i) { - Entry entry(trans, GET_BY_HANDLE, handles[i]); - if (!entry.good()) { - NOTREACHED(); - return false; - } - if (EntryNeedsEncryption(encrypted_types, entry)) - return false; - } - return true; -} - -bool EntryNeedsEncryption(ModelTypeSet encrypted_types, - const Entry& entry) { - if (!entry.GetUniqueServerTag().empty()) - return false; // We don't encrypt unique server nodes. - ModelType type = entry.GetModelType(); - if (type == PASSWORDS || IsControlType(type)) - return false; - // Checking NON_UNIQUE_NAME is not necessary for the correctness of encrypting - // the data, nor for determining if data is encrypted. We simply ensure it has - // been overwritten to avoid any possible leaks of sensitive data. - return SpecificsNeedsEncryption(encrypted_types, entry.GetSpecifics()) || - (encrypted_types.Has(type) && - entry.GetNonUniqueName() != kEncryptedString); -} - -bool SpecificsNeedsEncryption(ModelTypeSet encrypted_types, - const sync_pb::EntitySpecifics& specifics) { - const ModelType type = GetModelTypeFromSpecifics(specifics); - if (type == PASSWORDS || IsControlType(type)) - return false; // These types have their own encryption schemes. - if (!encrypted_types.Has(type)) - return false; // This type does not require encryption - return !specifics.has_encrypted(); -} - -// Mainly for testing. -bool VerifyDataTypeEncryptionForTest( - BaseTransaction* const trans, - ModelType type, - bool is_encrypted) { - Cryptographer* cryptographer = trans->directory()->GetCryptographer(trans); - if (type == PASSWORDS || IsControlType(type)) { - NOTREACHED(); - return true; - } - std::string type_tag = ModelTypeToRootTag(type); - Entry type_root(trans, GET_BY_SERVER_TAG, type_tag); - if (!type_root.good()) { - NOTREACHED(); - return false; - } - - std::queue<Id> to_visit; - Id id_string = type_root.GetFirstChildId(); - to_visit.push(id_string); - while (!to_visit.empty()) { - id_string = to_visit.front(); - to_visit.pop(); - if (id_string.IsRoot()) - continue; - - Entry child(trans, GET_BY_ID, id_string); - if (!child.good()) { - NOTREACHED(); - return false; - } - if (child.GetIsDir()) { - Id child_id_string = child.GetFirstChildId(); - // Traverse the children. - to_visit.push(child_id_string); - } - const sync_pb::EntitySpecifics& specifics = child.GetSpecifics(); - DCHECK_EQ(type, child.GetModelType()); - DCHECK_EQ(type, GetModelTypeFromSpecifics(specifics)); - // We don't encrypt the server's permanent items. - if (child.GetUniqueServerTag().empty()) { - if (specifics.has_encrypted() != is_encrypted) - return false; - if (specifics.has_encrypted()) { - if (child.GetNonUniqueName() != kEncryptedString) - return false; - if (!cryptographer->CanDecryptUsingDefaultKey(specifics.encrypted())) - return false; - } - } - // Push the successor. - to_visit.push(child.GetSuccessorId()); - } - return true; -} - -bool UpdateEntryWithEncryption( - BaseTransaction* const trans, - const sync_pb::EntitySpecifics& new_specifics, - syncable::MutableEntry* entry) { - NigoriHandler* nigori_handler = trans->directory()->GetNigoriHandler(); - Cryptographer* cryptographer = trans->directory()->GetCryptographer(trans); - ModelType type = GetModelTypeFromSpecifics(new_specifics); - DCHECK_GE(type, FIRST_REAL_MODEL_TYPE); - const sync_pb::EntitySpecifics& old_specifics = entry->GetSpecifics(); - const ModelTypeSet encrypted_types = nigori_handler->GetEncryptedTypes(trans); - // It's possible the nigori lost the set of encrypted types. If the current - // specifics are already encrypted, we want to ensure we continue encrypting. - bool was_encrypted = old_specifics.has_encrypted(); - sync_pb::EntitySpecifics generated_specifics; - if (new_specifics.has_encrypted()) { - NOTREACHED() << "New specifics already has an encrypted blob."; - return false; - } - if ((!SpecificsNeedsEncryption(encrypted_types, new_specifics) && - !was_encrypted) || - !cryptographer->is_initialized()) { - // No encryption required or we are unable to encrypt. - generated_specifics.CopyFrom(new_specifics); - } else { - // Encrypt new_specifics into generated_specifics. - if (VLOG_IS_ON(2)) { - scoped_ptr<base::DictionaryValue> value(entry->ToValue(NULL)); - std::string info; - base::JSONWriter::WriteWithOptions(value.get(), - base::JSONWriter::OPTIONS_PRETTY_PRINT, - &info); - DVLOG(2) << "Encrypting specifics of type " - << ModelTypeToString(type) - << " with content: " - << info; - } - // Only copy over the old specifics if it is of the right type and already - // encrypted. The first time we encrypt a node we start from scratch, hence - // removing all the unencrypted data, but from then on we only want to - // update the node if the data changes or the encryption key changes. - if (GetModelTypeFromSpecifics(old_specifics) == type && - was_encrypted) { - generated_specifics.CopyFrom(old_specifics); - } else { - AddDefaultFieldValue(type, &generated_specifics); - } - // Does not change anything if underlying encrypted blob was already up - // to date and encrypted with the default key. - if (!cryptographer->Encrypt(new_specifics, - generated_specifics.mutable_encrypted())) { - NOTREACHED() << "Could not encrypt data for node of type " - << ModelTypeToString(type); - return false; - } - } - - // It's possible this entry was encrypted but didn't properly overwrite the - // non_unique_name (see crbug.com/96314). - bool encrypted_without_overwriting_name = (was_encrypted && - entry->GetNonUniqueName() != kEncryptedString); - - // If we're encrypted but the name wasn't overwritten properly we still want - // to rewrite the entry, irrespective of whether the specifics match. - if (!encrypted_without_overwriting_name && - old_specifics.SerializeAsString() == - generated_specifics.SerializeAsString()) { - DVLOG(2) << "Specifics of type " << ModelTypeToString(type) - << " already match, dropping change."; - return true; - } - - if (generated_specifics.has_encrypted()) { - // Overwrite the possibly sensitive non-specifics data. - entry->PutNonUniqueName(kEncryptedString); - // For bookmarks we actually put bogus data into the unencrypted specifics, - // else the server will try to do it for us. - if (type == BOOKMARKS) { - sync_pb::BookmarkSpecifics* bookmark_specifics = - generated_specifics.mutable_bookmark(); - if (!entry->GetIsDir()) - bookmark_specifics->set_url(kEncryptedString); - bookmark_specifics->set_title(kEncryptedString); - } - } - entry->PutSpecifics(generated_specifics); - DVLOG(1) << "Overwriting specifics of type " - << ModelTypeToString(type) - << " and marking for syncing."; - syncable::MarkForSyncing(entry); - return true; -} - -void UpdateNigoriFromEncryptedTypes(ModelTypeSet encrypted_types, - bool encrypt_everything, - sync_pb::NigoriSpecifics* nigori) { - nigori->set_encrypt_everything(encrypt_everything); - COMPILE_ASSERT(30 == MODEL_TYPE_COUNT, UpdateEncryptedTypes); - nigori->set_encrypt_bookmarks( - encrypted_types.Has(BOOKMARKS)); - nigori->set_encrypt_preferences( - encrypted_types.Has(PREFERENCES)); - nigori->set_encrypt_autofill_profile( - encrypted_types.Has(AUTOFILL_PROFILE)); - nigori->set_encrypt_autofill(encrypted_types.Has(AUTOFILL)); - nigori->set_encrypt_themes(encrypted_types.Has(THEMES)); - nigori->set_encrypt_typed_urls( - encrypted_types.Has(TYPED_URLS)); - nigori->set_encrypt_extension_settings( - encrypted_types.Has(EXTENSION_SETTINGS)); - nigori->set_encrypt_extensions( - encrypted_types.Has(EXTENSIONS)); - nigori->set_encrypt_search_engines( - encrypted_types.Has(SEARCH_ENGINES)); - nigori->set_encrypt_sessions(encrypted_types.Has(SESSIONS)); - nigori->set_encrypt_app_settings( - encrypted_types.Has(APP_SETTINGS)); - nigori->set_encrypt_apps(encrypted_types.Has(APPS)); - nigori->set_encrypt_app_notifications( - encrypted_types.Has(APP_NOTIFICATIONS)); - nigori->set_encrypt_dictionary(encrypted_types.Has(DICTIONARY)); - nigori->set_encrypt_favicon_images(encrypted_types.Has(FAVICON_IMAGES)); - nigori->set_encrypt_favicon_tracking(encrypted_types.Has(FAVICON_TRACKING)); - nigori->set_encrypt_articles(encrypted_types.Has(ARTICLES)); - nigori->set_encrypt_app_list(encrypted_types.Has(APP_LIST)); -} - -ModelTypeSet GetEncryptedTypesFromNigori( - const sync_pb::NigoriSpecifics& nigori) { - if (nigori.encrypt_everything()) - return ModelTypeSet::All(); - - ModelTypeSet encrypted_types; - COMPILE_ASSERT(30 == MODEL_TYPE_COUNT, UpdateEncryptedTypes); - if (nigori.encrypt_bookmarks()) - encrypted_types.Put(BOOKMARKS); - if (nigori.encrypt_preferences()) - encrypted_types.Put(PREFERENCES); - if (nigori.encrypt_autofill_profile()) - encrypted_types.Put(AUTOFILL_PROFILE); - if (nigori.encrypt_autofill()) - encrypted_types.Put(AUTOFILL); - if (nigori.encrypt_themes()) - encrypted_types.Put(THEMES); - if (nigori.encrypt_typed_urls()) - encrypted_types.Put(TYPED_URLS); - if (nigori.encrypt_extension_settings()) - encrypted_types.Put(EXTENSION_SETTINGS); - if (nigori.encrypt_extensions()) - encrypted_types.Put(EXTENSIONS); - if (nigori.encrypt_search_engines()) - encrypted_types.Put(SEARCH_ENGINES); - if (nigori.encrypt_sessions()) - encrypted_types.Put(SESSIONS); - if (nigori.encrypt_app_settings()) - encrypted_types.Put(APP_SETTINGS); - if (nigori.encrypt_apps()) - encrypted_types.Put(APPS); - if (nigori.encrypt_app_notifications()) - encrypted_types.Put(APP_NOTIFICATIONS); - if (nigori.encrypt_dictionary()) - encrypted_types.Put(DICTIONARY); - if (nigori.encrypt_favicon_images()) - encrypted_types.Put(FAVICON_IMAGES); - if (nigori.encrypt_favicon_tracking()) - encrypted_types.Put(FAVICON_TRACKING); - if (nigori.encrypt_articles()) - encrypted_types.Put(ARTICLES); - if (nigori.encrypt_app_list()) - encrypted_types.Put(APP_LIST); - return encrypted_types; -} - -} // namespace syncable -} // namespace syncer |