services/sync/tests/unit/test_service_detect_upgrade.js

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /* Any copyright is dedicated to the Public Domain.
michael@0 2 * http://creativecommons.org/publicdomain/zero/1.0/ */
michael@0 3
michael@0 4 Cu.import("resource://gre/modules/Log.jsm");
michael@0 5 Cu.import("resource://services-sync/constants.js");
michael@0 6 Cu.import("resource://services-sync/keys.js");
michael@0 7 Cu.import("resource://services-sync/engines/tabs.js");
michael@0 8 Cu.import("resource://services-sync/engines.js");
michael@0 9 Cu.import("resource://services-sync/record.js");
michael@0 10 Cu.import("resource://services-sync/service.js");
michael@0 11 Cu.import("resource://services-sync/util.js");
michael@0 12 Cu.import("resource://testing-common/services/sync/utils.js");
michael@0 13
michael@0 14 Service.engineManager.register(TabEngine);
michael@0 15
michael@0 16 add_test(function v4_upgrade() {
michael@0 17 let passphrase = "abcdeabcdeabcdeabcdeabcdea";
michael@0 18
michael@0 19 let clients = new ServerCollection();
michael@0 20 let meta_global = new ServerWBO('global');
michael@0 21
michael@0 22 // Tracking info/collections.
michael@0 23 let collectionsHelper = track_collections_helper();
michael@0 24 let upd = collectionsHelper.with_updated_collection;
michael@0 25 let collections = collectionsHelper.collections;
michael@0 26
michael@0 27 let keysWBO = new ServerWBO("keys");
michael@0 28 let server = httpd_setup({
michael@0 29 // Special.
michael@0 30 "/1.1/johndoe/info/collections": collectionsHelper.handler,
michael@0 31 "/1.1/johndoe/storage/crypto/keys": upd("crypto", keysWBO.handler()),
michael@0 32 "/1.1/johndoe/storage/meta/global": upd("meta", meta_global.handler()),
michael@0 33
michael@0 34 // Track modified times.
michael@0 35 "/1.1/johndoe/storage/clients": upd("clients", clients.handler()),
michael@0 36 "/1.1/johndoe/storage/tabs": upd("tabs", new ServerCollection().handler()),
michael@0 37
michael@0 38 // Just so we don't get 404s in the logs.
michael@0 39 "/1.1/johndoe/storage/bookmarks": new ServerCollection().handler(),
michael@0 40 "/1.1/johndoe/storage/forms": new ServerCollection().handler(),
michael@0 41 "/1.1/johndoe/storage/history": new ServerCollection().handler(),
michael@0 42 "/1.1/johndoe/storage/passwords": new ServerCollection().handler(),
michael@0 43 "/1.1/johndoe/storage/prefs": new ServerCollection().handler()
michael@0 44 });
michael@0 45
michael@0 46 ensureLegacyIdentityManager();
michael@0 47
michael@0 48 try {
michael@0 49
michael@0 50 _("Set up some tabs.");
michael@0 51 let myTabs =
michael@0 52 {windows: [{tabs: [{index: 1,
michael@0 53 entries: [{
michael@0 54 url: "http://foo.com/",
michael@0 55 title: "Title"
michael@0 56 }],
michael@0 57 attributes: {
michael@0 58 image: "image"
michael@0 59 }
michael@0 60 }]}]};
michael@0 61 delete Svc.Session;
michael@0 62 Svc.Session = {
michael@0 63 getBrowserState: function () JSON.stringify(myTabs)
michael@0 64 };
michael@0 65
michael@0 66 Service.status.resetSync();
michael@0 67
michael@0 68 _("Logging in.");
michael@0 69 Service.serverURL = server.baseURI;
michael@0 70
michael@0 71 Service.login("johndoe", "ilovejane", passphrase);
michael@0 72 do_check_true(Service.isLoggedIn);
michael@0 73 Service.verifyAndFetchSymmetricKeys();
michael@0 74 do_check_true(Service._remoteSetup());
michael@0 75
michael@0 76 function test_out_of_date() {
michael@0 77 _("Old meta/global: " + JSON.stringify(meta_global));
michael@0 78 meta_global.payload = JSON.stringify({"syncID": "foooooooooooooooooooooooooo",
michael@0 79 "storageVersion": STORAGE_VERSION + 1});
michael@0 80 collections.meta = Date.now() / 1000;
michael@0 81 _("New meta/global: " + JSON.stringify(meta_global));
michael@0 82 Service.recordManager.set(Service.metaURL, meta_global);
michael@0 83 try {
michael@0 84 Service.sync();
michael@0 85 }
michael@0 86 catch (ex) {
michael@0 87 }
michael@0 88 do_check_eq(Service.status.sync, VERSION_OUT_OF_DATE);
michael@0 89 }
michael@0 90
michael@0 91 // See what happens when we bump the storage version.
michael@0 92 _("Syncing after server has been upgraded.");
michael@0 93 test_out_of_date();
michael@0 94
michael@0 95 // Same should happen after a wipe.
michael@0 96 _("Syncing after server has been upgraded and wiped.");
michael@0 97 Service.wipeServer();
michael@0 98 test_out_of_date();
michael@0 99
michael@0 100 // Now's a great time to test what happens when keys get replaced.
michael@0 101 _("Syncing afresh...");
michael@0 102 Service.logout();
michael@0 103 Service.collectionKeys.clear();
michael@0 104 Service.serverURL = server.baseURI;
michael@0 105 meta_global.payload = JSON.stringify({"syncID": "foooooooooooooobbbbbbbbbbbb",
michael@0 106 "storageVersion": STORAGE_VERSION});
michael@0 107 collections.meta = Date.now() / 1000;
michael@0 108 Service.recordManager.set(Service.metaURL, meta_global);
michael@0 109 Service.login("johndoe", "ilovejane", passphrase);
michael@0 110 do_check_true(Service.isLoggedIn);
michael@0 111 Service.sync();
michael@0 112 do_check_true(Service.isLoggedIn);
michael@0 113
michael@0 114 let serverDecrypted;
michael@0 115 let serverKeys;
michael@0 116 let serverResp;
michael@0 117
michael@0 118
michael@0 119 function retrieve_server_default() {
michael@0 120 serverKeys = serverResp = serverDecrypted = null;
michael@0 121
michael@0 122 serverKeys = new CryptoWrapper("crypto", "keys");
michael@0 123 serverResp = serverKeys.fetch(Service.resource(Service.cryptoKeysURL)).response;
michael@0 124 do_check_true(serverResp.success);
michael@0 125
michael@0 126 serverDecrypted = serverKeys.decrypt(Service.identity.syncKeyBundle);
michael@0 127 _("Retrieved WBO: " + JSON.stringify(serverDecrypted));
michael@0 128 _("serverKeys: " + JSON.stringify(serverKeys));
michael@0 129
michael@0 130 return serverDecrypted.default;
michael@0 131 }
michael@0 132
michael@0 133 function retrieve_and_compare_default(should_succeed) {
michael@0 134 let serverDefault = retrieve_server_default();
michael@0 135 let localDefault = Service.collectionKeys.keyForCollection().keyPairB64;
michael@0 136
michael@0 137 _("Retrieved keyBundle: " + JSON.stringify(serverDefault));
michael@0 138 _("Local keyBundle: " + JSON.stringify(localDefault));
michael@0 139
michael@0 140 if (should_succeed)
michael@0 141 do_check_eq(JSON.stringify(serverDefault), JSON.stringify(localDefault));
michael@0 142 else
michael@0 143 do_check_neq(JSON.stringify(serverDefault), JSON.stringify(localDefault));
michael@0 144 }
michael@0 145
michael@0 146 // Uses the objects set above.
michael@0 147 function set_server_keys(pair) {
michael@0 148 serverDecrypted.default = pair;
michael@0 149 serverKeys.cleartext = serverDecrypted;
michael@0 150 serverKeys.encrypt(Service.identity.syncKeyBundle);
michael@0 151 serverKeys.upload(Service.resource(Service.cryptoKeysURL));
michael@0 152 }
michael@0 153
michael@0 154 _("Checking we have the latest keys.");
michael@0 155 retrieve_and_compare_default(true);
michael@0 156
michael@0 157 _("Update keys on server.");
michael@0 158 set_server_keys(["KaaaaaaaaaaaHAtfmuRY0XEJ7LXfFuqvF7opFdBD/MY=",
michael@0 159 "aaaaaaaaaaaapxMO6TEWtLIOv9dj6kBAJdzhWDkkkis="]);
michael@0 160
michael@0 161 _("Checking that we no longer have the latest keys.");
michael@0 162 retrieve_and_compare_default(false);
michael@0 163
michael@0 164 _("Indeed, they're what we set them to...");
michael@0 165 do_check_eq("KaaaaaaaaaaaHAtfmuRY0XEJ7LXfFuqvF7opFdBD/MY=",
michael@0 166 retrieve_server_default()[0]);
michael@0 167
michael@0 168 _("Sync. Should download changed keys automatically.");
michael@0 169 let oldClientsModified = collections.clients;
michael@0 170 let oldTabsModified = collections.tabs;
michael@0 171
michael@0 172 Service.login("johndoe", "ilovejane", passphrase);
michael@0 173 Service.sync();
michael@0 174 _("New key should have forced upload of data.");
michael@0 175 _("Tabs: " + oldTabsModified + " < " + collections.tabs);
michael@0 176 _("Clients: " + oldClientsModified + " < " + collections.clients);
michael@0 177 do_check_true(collections.clients > oldClientsModified);
michael@0 178 do_check_true(collections.tabs > oldTabsModified);
michael@0 179
michael@0 180 _("... and keys will now match.");
michael@0 181 retrieve_and_compare_default(true);
michael@0 182
michael@0 183 // Clean up.
michael@0 184 Service.startOver();
michael@0 185
michael@0 186 } finally {
michael@0 187 Svc.Prefs.resetBranch("");
michael@0 188 server.stop(run_next_test);
michael@0 189 }
michael@0 190 });
michael@0 191
michael@0 192 add_test(function v5_upgrade() {
michael@0 193 let passphrase = "abcdeabcdeabcdeabcdeabcdea";
michael@0 194
michael@0 195 // Tracking info/collections.
michael@0 196 let collectionsHelper = track_collections_helper();
michael@0 197 let upd = collectionsHelper.with_updated_collection;
michael@0 198 let collections = collectionsHelper.collections;
michael@0 199
michael@0 200 let keysWBO = new ServerWBO("keys");
michael@0 201 let bulkWBO = new ServerWBO("bulk");
michael@0 202 let clients = new ServerCollection();
michael@0 203 let meta_global = new ServerWBO('global');
michael@0 204
michael@0 205 let server = httpd_setup({
michael@0 206 // Special.
michael@0 207 "/1.1/johndoe/storage/meta/global": upd("meta", meta_global.handler()),
michael@0 208 "/1.1/johndoe/info/collections": collectionsHelper.handler,
michael@0 209 "/1.1/johndoe/storage/crypto/keys": upd("crypto", keysWBO.handler()),
michael@0 210 "/1.1/johndoe/storage/crypto/bulk": upd("crypto", bulkWBO.handler()),
michael@0 211
michael@0 212 // Track modified times.
michael@0 213 "/1.1/johndoe/storage/clients": upd("clients", clients.handler()),
michael@0 214 "/1.1/johndoe/storage/tabs": upd("tabs", new ServerCollection().handler()),
michael@0 215 });
michael@0 216
michael@0 217 try {
michael@0 218
michael@0 219 _("Set up some tabs.");
michael@0 220 let myTabs =
michael@0 221 {windows: [{tabs: [{index: 1,
michael@0 222 entries: [{
michael@0 223 url: "http://foo.com/",
michael@0 224 title: "Title"
michael@0 225 }],
michael@0 226 attributes: {
michael@0 227 image: "image"
michael@0 228 }
michael@0 229 }]}]};
michael@0 230 delete Svc.Session;
michael@0 231 Svc.Session = {
michael@0 232 getBrowserState: function () JSON.stringify(myTabs)
michael@0 233 };
michael@0 234
michael@0 235 Service.status.resetSync();
michael@0 236
michael@0 237 setBasicCredentials("johndoe", "ilovejane", passphrase);
michael@0 238 Service.serverURL = server.baseURI + "/";
michael@0 239 Service.clusterURL = server.baseURI + "/";
michael@0 240
michael@0 241 // Test an upgrade where the contents of the server would cause us to error
michael@0 242 // -- keys decrypted with a different sync key, for example.
michael@0 243 _("Testing v4 -> v5 (or similar) upgrade.");
michael@0 244 function update_server_keys(syncKeyBundle, wboName, collWBO) {
michael@0 245 generateNewKeys(Service.collectionKeys);
michael@0 246 serverKeys = Service.collectionKeys.asWBO("crypto", wboName);
michael@0 247 serverKeys.encrypt(syncKeyBundle);
michael@0 248 let res = Service.resource(Service.storageURL + collWBO);
michael@0 249 do_check_true(serverKeys.upload(res).success);
michael@0 250 }
michael@0 251
michael@0 252 _("Bumping version.");
michael@0 253 // Bump version on the server.
michael@0 254 let m = new WBORecord("meta", "global");
michael@0 255 m.payload = {"syncID": "foooooooooooooooooooooooooo",
michael@0 256 "storageVersion": STORAGE_VERSION + 1};
michael@0 257 m.upload(Service.resource(Service.metaURL));
michael@0 258
michael@0 259 _("New meta/global: " + JSON.stringify(meta_global));
michael@0 260
michael@0 261 // Fill the keys with bad data.
michael@0 262 let badKeys = new SyncKeyBundle("foobar", "aaaaaaaaaaaaaaaaaaaaaaaaaa");
michael@0 263 update_server_keys(badKeys, "keys", "crypto/keys"); // v4
michael@0 264 update_server_keys(badKeys, "bulk", "crypto/bulk"); // v5
michael@0 265
michael@0 266 _("Generating new keys.");
michael@0 267 generateNewKeys(Service.collectionKeys);
michael@0 268
michael@0 269 // Now sync and see what happens. It should be a version fail, not a crypto
michael@0 270 // fail.
michael@0 271
michael@0 272 _("Logging in.");
michael@0 273 try {
michael@0 274 Service.login("johndoe", "ilovejane", passphrase);
michael@0 275 }
michael@0 276 catch (e) {
michael@0 277 _("Exception: " + e);
michael@0 278 }
michael@0 279 _("Status: " + Service.status);
michael@0 280 do_check_false(Service.isLoggedIn);
michael@0 281 do_check_eq(VERSION_OUT_OF_DATE, Service.status.sync);
michael@0 282
michael@0 283 // Clean up.
michael@0 284 Service.startOver();
michael@0 285
michael@0 286 } finally {
michael@0 287 Svc.Prefs.resetBranch("");
michael@0 288 server.stop(run_next_test);
michael@0 289 }
michael@0 290 });
michael@0 291
michael@0 292 function run_test() {
michael@0 293 let logger = Log.repository.rootLogger;
michael@0 294 Log.repository.rootLogger.addAppender(new Log.DumpAppender());
michael@0 295
michael@0 296 run_next_test();
michael@0 297 }

mercurial