| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/sync/syncable/nigori_util.h" | |
| 6 | |
| 7 #include <queue> | |
| 8 #include <string> | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "chrome/browser/sync/engine/syncapi.h" | |
| 12 #include "chrome/browser/sync/engine/syncer_util.h" | |
| 13 #include "chrome/browser/sync/syncable/syncable.h" | |
| 14 #include "chrome/browser/sync/util/cryptographer.h" | |
| 15 | |
| 16 namespace syncable { | |
| 17 void FillNigoriEncryptedTypes(const ModelTypeSet& types, | |
| 18 sync_pb::NigoriSpecifics* nigori) { | |
| 19 DCHECK(nigori); | |
| 20 nigori->set_encrypt_bookmarks(types.count(BOOKMARKS) > 0); | |
| 21 nigori->set_encrypt_preferences(types.count(PREFERENCES) > 0); | |
| 22 nigori->set_encrypt_autofill_profile(types.count(AUTOFILL_PROFILE) > 0); | |
| 23 nigori->set_encrypt_autofill(types.count(AUTOFILL) > 0); | |
| 24 nigori->set_encrypt_themes(types.count(THEMES) > 0); | |
| 25 nigori->set_encrypt_typed_urls(types.count(TYPED_URLS) > 0); | |
| 26 nigori->set_encrypt_extensions(types.count(EXTENSIONS) > 0); | |
| 27 nigori->set_encrypt_search_engines(types.count(SEARCH_ENGINES) > 0); | |
| 28 nigori->set_encrypt_sessions(types.count(SESSIONS) > 0); | |
| 29 nigori->set_encrypt_apps(types.count(APPS) > 0); | |
| 30 } | |
| 31 | |
| 32 bool ProcessUnsyncedChangesForEncryption( | |
| 33 WriteTransaction* const trans, | |
| 34 browser_sync::Cryptographer* cryptographer) { | |
| 35 DCHECK(cryptographer->is_ready()); | |
| 36 syncable::ModelTypeSet encrypted_types = cryptographer->GetEncryptedTypes(); | |
| 37 | |
| 38 // Get list of all datatypes with unsynced changes. It's possible that our | |
| 39 // local changes need to be encrypted if encryption for that datatype was | |
| 40 // just turned on (and vice versa). This should never affect passwords. | |
| 41 std::vector<int64> handles; | |
| 42 browser_sync::SyncerUtil::GetUnsyncedEntries(trans, &handles); | |
| 43 for (size_t i = 0; i < handles.size(); ++i) { | |
| 44 MutableEntry entry(trans, GET_BY_HANDLE, handles[i]); | |
| 45 if (!sync_api::WriteNode::UpdateEntryWithEncryption(cryptographer, | |
| 46 entry.Get(SPECIFICS), | |
| 47 &entry)) { | |
| 48 NOTREACHED(); | |
| 49 return false; | |
| 50 } | |
| 51 } | |
| 52 return true; | |
| 53 } | |
| 54 | |
| 55 bool VerifyUnsyncedChangesAreEncrypted( | |
| 56 BaseTransaction* const trans, | |
| 57 const ModelTypeSet& encrypted_types) { | |
| 58 std::vector<int64> handles; | |
| 59 browser_sync::SyncerUtil::GetUnsyncedEntries(trans, &handles); | |
| 60 for (size_t i = 0; i < handles.size(); ++i) { | |
| 61 Entry entry(trans, GET_BY_HANDLE, handles[i]); | |
| 62 if (!entry.good()) { | |
| 63 NOTREACHED(); | |
| 64 return false; | |
| 65 } | |
| 66 const sync_pb::EntitySpecifics& entry_specifics = entry.Get(SPECIFICS); | |
| 67 ModelType type = entry.GetModelType(); | |
| 68 if (type == PASSWORDS) | |
| 69 continue; | |
| 70 if (encrypted_types.count(type) > 0 && | |
| 71 !entry_specifics.has_encrypted()) { | |
| 72 // This datatype requires encryption but this data is not encrypted. | |
| 73 return false; | |
| 74 } | |
| 75 } | |
| 76 return true; | |
| 77 } | |
| 78 | |
| 79 // Mainly for testing. | |
| 80 bool VerifyDataTypeEncryption(BaseTransaction* const trans, | |
| 81 browser_sync::Cryptographer* cryptographer, | |
| 82 ModelType type, | |
| 83 bool is_encrypted) { | |
| 84 if (type == PASSWORDS || type == NIGORI) { | |
| 85 NOTREACHED(); | |
| 86 return true; | |
| 87 } | |
| 88 std::string type_tag = ModelTypeToRootTag(type); | |
| 89 Entry type_root(trans, GET_BY_SERVER_TAG, type_tag); | |
| 90 if (!type_root.good()) { | |
| 91 NOTREACHED(); | |
| 92 return false; | |
| 93 } | |
| 94 | |
| 95 std::queue<Id> to_visit; | |
| 96 Id id_string = | |
| 97 trans->directory()->GetFirstChildId(trans, type_root.Get(ID)); | |
| 98 to_visit.push(id_string); | |
| 99 while (!to_visit.empty()) { | |
| 100 id_string = to_visit.front(); | |
| 101 to_visit.pop(); | |
| 102 if (id_string.IsRoot()) | |
| 103 continue; | |
| 104 | |
| 105 Entry child(trans, GET_BY_ID, id_string); | |
| 106 if (!child.good()) { | |
| 107 NOTREACHED(); | |
| 108 return false; | |
| 109 } | |
| 110 if (child.Get(IS_DIR)) { | |
| 111 // Traverse the children. | |
| 112 to_visit.push( | |
| 113 trans->directory()->GetFirstChildId(trans, child.Get(ID))); | |
| 114 } | |
| 115 const sync_pb::EntitySpecifics& specifics = child.Get(SPECIFICS); | |
| 116 DCHECK_EQ(type, child.GetModelType()); | |
| 117 DCHECK_EQ(type, GetModelTypeFromSpecifics(specifics)); | |
| 118 // We don't encrypt the server's permanent items. | |
| 119 if (child.Get(UNIQUE_SERVER_TAG).empty()) { | |
| 120 if (specifics.has_encrypted() != is_encrypted) | |
| 121 return false; | |
| 122 if (specifics.has_encrypted()) { | |
| 123 if (child.Get(NON_UNIQUE_NAME) != kEncryptedString) | |
| 124 return false; | |
| 125 if (!cryptographer->CanDecryptUsingDefaultKey(specifics.encrypted())) | |
| 126 return false; | |
| 127 } | |
| 128 } | |
| 129 // Push the successor. | |
| 130 to_visit.push(child.Get(NEXT_ID)); | |
| 131 } | |
| 132 return true; | |
| 133 } | |
| 134 | |
| 135 } // namespace syncable | |
| OLD | NEW |