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