services/sync/tests/unit/test_corrupt_keys.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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/PlacesUtils.jsm");
michael@0 5 Cu.import("resource://gre/modules/Log.jsm");
michael@0 6 Cu.import("resource://services-sync/constants.js");
michael@0 7 Cu.import("resource://services-sync/engines.js");
michael@0 8 Cu.import("resource://services-sync/engines/tabs.js");
michael@0 9 Cu.import("resource://services-sync/engines/history.js");
michael@0 10 Cu.import("resource://services-sync/record.js");
michael@0 11 Cu.import("resource://services-sync/service.js");
michael@0 12 Cu.import("resource://services-sync/status.js");
michael@0 13 Cu.import("resource://services-sync/util.js");
michael@0 14 Cu.import("resource://testing-common/services/sync/utils.js");
michael@0 15 Cu.import("resource://gre/modules/Promise.jsm");
michael@0 16
michael@0 17 add_task(function test_locally_changed_keys() {
michael@0 18 let passphrase = "abcdeabcdeabcdeabcdeabcdea";
michael@0 19
michael@0 20 let hmacErrorCount = 0;
michael@0 21 function counting(f) {
michael@0 22 return function() {
michael@0 23 hmacErrorCount++;
michael@0 24 return f.call(this);
michael@0 25 };
michael@0 26 }
michael@0 27
michael@0 28 Service.handleHMACEvent = counting(Service.handleHMACEvent);
michael@0 29
michael@0 30 let server = new SyncServer();
michael@0 31 let johndoe = server.registerUser("johndoe", "password");
michael@0 32 johndoe.createContents({
michael@0 33 meta: {},
michael@0 34 crypto: {},
michael@0 35 clients: {}
michael@0 36 });
michael@0 37 server.start();
michael@0 38
michael@0 39 try {
michael@0 40 Svc.Prefs.set("registerEngines", "Tab");
michael@0 41 _("Set up some tabs.");
michael@0 42 let myTabs =
michael@0 43 {windows: [{tabs: [{index: 1,
michael@0 44 entries: [{
michael@0 45 url: "http://foo.com/",
michael@0 46 title: "Title"
michael@0 47 }],
michael@0 48 attributes: {
michael@0 49 image: "image"
michael@0 50 }
michael@0 51 }]}]};
michael@0 52 delete Svc.Session;
michael@0 53 Svc.Session = {
michael@0 54 getBrowserState: function () JSON.stringify(myTabs)
michael@0 55 };
michael@0 56
michael@0 57 setBasicCredentials("johndoe", "password", passphrase);
michael@0 58 Service.serverURL = server.baseURI;
michael@0 59 Service.clusterURL = server.baseURI;
michael@0 60
michael@0 61 Service.engineManager.register(HistoryEngine);
michael@0 62
michael@0 63 function corrupt_local_keys() {
michael@0 64 Service.collectionKeys._default.keyPair = [Svc.Crypto.generateRandomKey(),
michael@0 65 Svc.Crypto.generateRandomKey()];
michael@0 66 }
michael@0 67
michael@0 68 _("Setting meta.");
michael@0 69
michael@0 70 // Bump version on the server.
michael@0 71 let m = new WBORecord("meta", "global");
michael@0 72 m.payload = {"syncID": "foooooooooooooooooooooooooo",
michael@0 73 "storageVersion": STORAGE_VERSION};
michael@0 74 m.upload(Service.resource(Service.metaURL));
michael@0 75
michael@0 76 _("New meta/global: " + JSON.stringify(johndoe.collection("meta").wbo("global")));
michael@0 77
michael@0 78 // Upload keys.
michael@0 79 generateNewKeys(Service.collectionKeys);
michael@0 80 let serverKeys = Service.collectionKeys.asWBO("crypto", "keys");
michael@0 81 serverKeys.encrypt(Service.identity.syncKeyBundle);
michael@0 82 do_check_true(serverKeys.upload(Service.resource(Service.cryptoKeysURL)).success);
michael@0 83
michael@0 84 // Check that login works.
michael@0 85 do_check_true(Service.login("johndoe", "ilovejane", passphrase));
michael@0 86 do_check_true(Service.isLoggedIn);
michael@0 87
michael@0 88 // Sync should upload records.
michael@0 89 Service.sync();
michael@0 90
michael@0 91 // Tabs exist.
michael@0 92 _("Tabs modified: " + johndoe.modified("tabs"));
michael@0 93 do_check_true(johndoe.modified("tabs") > 0);
michael@0 94
michael@0 95 let coll_modified = Service.collectionKeys.lastModified;
michael@0 96
michael@0 97 // Let's create some server side history records.
michael@0 98 let liveKeys = Service.collectionKeys.keyForCollection("history");
michael@0 99 _("Keys now: " + liveKeys.keyPair);
michael@0 100 let visitType = Ci.nsINavHistoryService.TRANSITION_LINK;
michael@0 101 let history = johndoe.createCollection("history");
michael@0 102 for (let i = 0; i < 5; i++) {
michael@0 103 let id = 'record-no--' + i;
michael@0 104 let modified = Date.now()/1000 - 60*(i+10);
michael@0 105
michael@0 106 let w = new CryptoWrapper("history", "id");
michael@0 107 w.cleartext = {
michael@0 108 id: id,
michael@0 109 histUri: "http://foo/bar?" + id,
michael@0 110 title: id,
michael@0 111 sortindex: i,
michael@0 112 visits: [{date: (modified - 5) * 1000000, type: visitType}],
michael@0 113 deleted: false};
michael@0 114 w.encrypt(liveKeys);
michael@0 115
michael@0 116 let payload = {ciphertext: w.ciphertext,
michael@0 117 IV: w.IV,
michael@0 118 hmac: w.hmac};
michael@0 119 history.insert(id, payload, modified);
michael@0 120 }
michael@0 121
michael@0 122 history.timestamp = Date.now() / 1000;
michael@0 123 let old_key_time = johndoe.modified("crypto");
michael@0 124 _("Old key time: " + old_key_time);
michael@0 125
michael@0 126 // Check that we can decrypt one.
michael@0 127 let rec = new CryptoWrapper("history", "record-no--0");
michael@0 128 rec.fetch(Service.resource(Service.storageURL + "history/record-no--0"));
michael@0 129 _(JSON.stringify(rec));
michael@0 130 do_check_true(!!rec.decrypt(liveKeys));
michael@0 131
michael@0 132 do_check_eq(hmacErrorCount, 0);
michael@0 133
michael@0 134 // Fill local key cache with bad data.
michael@0 135 corrupt_local_keys();
michael@0 136 _("Keys now: " + Service.collectionKeys.keyForCollection("history").keyPair);
michael@0 137
michael@0 138 do_check_eq(hmacErrorCount, 0);
michael@0 139
michael@0 140 _("HMAC error count: " + hmacErrorCount);
michael@0 141 // Now syncing should succeed, after one HMAC error.
michael@0 142 Service.sync();
michael@0 143 do_check_eq(hmacErrorCount, 1);
michael@0 144 _("Keys now: " + Service.collectionKeys.keyForCollection("history").keyPair);
michael@0 145
michael@0 146 // And look! We downloaded history!
michael@0 147 let store = Service.engineManager.get("history")._store;
michael@0 148 do_check_true(yield promiseIsURIVisited("http://foo/bar?record-no--0"));
michael@0 149 do_check_true(yield promiseIsURIVisited("http://foo/bar?record-no--1"));
michael@0 150 do_check_true(yield promiseIsURIVisited("http://foo/bar?record-no--2"));
michael@0 151 do_check_true(yield promiseIsURIVisited("http://foo/bar?record-no--3"));
michael@0 152 do_check_true(yield promiseIsURIVisited("http://foo/bar?record-no--4"));
michael@0 153 do_check_eq(hmacErrorCount, 1);
michael@0 154
michael@0 155 _("Busting some new server values.");
michael@0 156 // Now what happens if we corrupt the HMAC on the server?
michael@0 157 for (let i = 5; i < 10; i++) {
michael@0 158 let id = 'record-no--' + i;
michael@0 159 let modified = 1 + (Date.now() / 1000);
michael@0 160
michael@0 161 let w = new CryptoWrapper("history", "id");
michael@0 162 w.cleartext = {
michael@0 163 id: id,
michael@0 164 histUri: "http://foo/bar?" + id,
michael@0 165 title: id,
michael@0 166 sortindex: i,
michael@0 167 visits: [{date: (modified - 5 ) * 1000000, type: visitType}],
michael@0 168 deleted: false};
michael@0 169 w.encrypt(Service.collectionKeys.keyForCollection("history"));
michael@0 170 w.hmac = w.hmac.toUpperCase();
michael@0 171
michael@0 172 let payload = {ciphertext: w.ciphertext,
michael@0 173 IV: w.IV,
michael@0 174 hmac: w.hmac};
michael@0 175 history.insert(id, payload, modified);
michael@0 176 }
michael@0 177 history.timestamp = Date.now() / 1000;
michael@0 178
michael@0 179 _("Server key time hasn't changed.");
michael@0 180 do_check_eq(johndoe.modified("crypto"), old_key_time);
michael@0 181
michael@0 182 _("Resetting HMAC error timer.");
michael@0 183 Service.lastHMACEvent = 0;
michael@0 184
michael@0 185 _("Syncing...");
michael@0 186 Service.sync();
michael@0 187 _("Keys now: " + Service.collectionKeys.keyForCollection("history").keyPair);
michael@0 188 _("Server keys have been updated, and we skipped over 5 more HMAC errors without adjusting history.");
michael@0 189 do_check_true(johndoe.modified("crypto") > old_key_time);
michael@0 190 do_check_eq(hmacErrorCount, 6);
michael@0 191 do_check_false(yield promiseIsURIVisited("http://foo/bar?record-no--5"));
michael@0 192 do_check_false(yield promiseIsURIVisited("http://foo/bar?record-no--6"));
michael@0 193 do_check_false(yield promiseIsURIVisited("http://foo/bar?record-no--7"));
michael@0 194 do_check_false(yield promiseIsURIVisited("http://foo/bar?record-no--8"));
michael@0 195 do_check_false(yield promiseIsURIVisited("http://foo/bar?record-no--9"));
michael@0 196 } finally {
michael@0 197 Svc.Prefs.resetBranch("");
michael@0 198 let deferred = Promise.defer();
michael@0 199 server.stop(deferred.resolve);
michael@0 200 yield deferred.promise;
michael@0 201 }
michael@0 202 });
michael@0 203
michael@0 204 function run_test() {
michael@0 205 let logger = Log.repository.rootLogger;
michael@0 206 Log.repository.rootLogger.addAppender(new Log.DumpAppender());
michael@0 207
michael@0 208 ensureLegacyIdentityManager();
michael@0 209
michael@0 210 run_next_test();
michael@0 211 }
michael@0 212
michael@0 213 /**
michael@0 214 * Asynchronously check a url is visited.
michael@0 215 * @param url the url
michael@0 216 * @return {Promise}
michael@0 217 * @resolves When the check has been added successfully.
michael@0 218 * @rejects JavaScript exception.
michael@0 219 */
michael@0 220 function promiseIsURIVisited(url) {
michael@0 221 let deferred = Promise.defer();
michael@0 222 PlacesUtils.asyncHistory.isURIVisited(Utils.makeURI(url), function(aURI, aIsVisited) {
michael@0 223 deferred.resolve(aIsVisited);
michael@0 224 });
michael@0 225
michael@0 226 return deferred.promise;
michael@0 227 }

mercurial