From 5ecb759622d3f98ce0ff38362202767c223bc1dd Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Fri, 14 Sep 2012 16:02:33 -0700 Subject: [PATCH] Bug 787273 - Part 5: Remove the CollectionKeys singleton; r=rnewman CollectionKeys is gone. Instead, we export CollectionKeyManager (the underlying type) and an instance is available on the Service singleton. --- services/sync/modules/engines.js | 22 +++++---- services/sync/modules/record.js | 22 ++++----- services/sync/modules/service.js | 26 +++++----- services/sync/tests/unit/head_helpers.js | 6 +-- .../sync/tests/unit/test_addons_engine.js | 2 +- .../sync/tests/unit/test_bookmark_engine.js | 2 +- .../sync/tests/unit/test_bookmark_record.js | 2 +- .../unit/test_bookmark_smart_bookmarks.js | 2 +- .../sync/tests/unit/test_clients_engine.js | 22 ++++----- services/sync/tests/unit/test_corrupt_keys.js | 24 +++++----- services/sync/tests/unit/test_engine_abort.js | 2 +- services/sync/tests/unit/test_errorhandler.js | 14 +++--- ...test_errorhandler_sync_checkServerError.js | 4 +- .../sync/tests/unit/test_history_engine.js | 2 +- services/sync/tests/unit/test_hmac_error.js | 4 +- .../sync/tests/unit/test_interval_triggers.js | 4 +- services/sync/tests/unit/test_keys.js | 48 ++++++++++--------- .../sync/tests/unit/test_records_crypto.js | 14 +++--- .../tests/unit/test_service_detect_upgrade.js | 10 ++-- .../unit/test_service_sync_remoteSetup.js | 8 ++-- .../test_service_sync_updateEnabledEngines.js | 6 +-- .../tests/unit/test_service_wipeClient.js | 6 +-- .../sync/tests/unit/test_syncengine_sync.js | 15 +++--- .../sync/tests/unit/test_syncscheduler.js | 8 ++-- 24 files changed, 138 insertions(+), 137 deletions(-) diff --git a/services/sync/modules/engines.js b/services/sync/modules/engines.js index 6864d583618d..4717acba210e 100644 --- a/services/sync/modules/engines.js +++ b/services/sync/modules/engines.js @@ -807,9 +807,12 @@ SyncEngine.prototype = { } } + let key = this.service.collectionKeys.keyForCollection(this.name); + // Not binding this method to 'this' for performance reasons. It gets // called for every incoming record. let self = this; + newitems.recordHandler = function(item) { if (aborting) { return; @@ -821,13 +824,13 @@ SyncEngine.prototype = { // Track the collection for the WBO. item.collection = self.name; - + // Remember which records were processed handled.push(item.id); try { try { - item.decrypt(); + item.decrypt(key); } catch (ex if Utils.isHMACMismatch(ex)) { let strategy = self.handleHMACMismatch(item, true); if (strategy == SyncEngine.kRecoveryStrategy.retry) { @@ -835,13 +838,14 @@ SyncEngine.prototype = { try { // Try decrypting again, typically because we've got new keys. self._log.info("Trying decrypt again..."); - item.decrypt(); + key = self.service.collectionKeys.keyForCollection(self.name); + item.decrypt(key); strategy = null; } catch (ex if Utils.isHMACMismatch(ex)) { strategy = self.handleHMACMismatch(item, false); } } - + switch (strategy) { case null: // Retry succeeded! No further handling. @@ -1242,7 +1246,7 @@ SyncEngine.prototype = { if (this._log.level <= Log4Moz.Level.Trace) this._log.trace("Outgoing: " + out); - out.encrypt(); + out.encrypt(this.service.collectionKeys.keyForCollection(this.name)); up.pushData(out); } catch(ex) { @@ -1324,10 +1328,12 @@ SyncEngine.prototype = { test.limit = 1; test.sort = "newest"; test.full = true; - test.recordHandler = function(record) { - record.decrypt(); + + let key = this.service.collectionKeys.keyForCollection(this.name); + test.recordHandler = function recordHandler(record) { + record.decrypt(key); canDecrypt = true; - }; + }.bind(this); // Any failure fetching/decrypting will just result in false try { diff --git a/services/sync/modules/record.js b/services/sync/modules/record.js index 8c91caac2b63..4f34ae26acd1 100644 --- a/services/sync/modules/record.js +++ b/services/sync/modules/record.js @@ -6,7 +6,7 @@ const EXPORTED_SYMBOLS = [ "WBORecord", "RecordManager", "CryptoWrapper", - "CollectionKeys", + "CollectionKeyManager", "Collection", ]; @@ -196,9 +196,8 @@ CryptoWrapper.prototype = { * Optional key bundle overrides the collection key lookup. */ encrypt: function encrypt(keyBundle) { - keyBundle = keyBundle || CollectionKeys.keyForCollection(this.collection); if (!keyBundle) { - throw new Error("Key bundle is null for " + this.uri.spec); + throw new Error("A key bundle must be supplied to encrypt."); } this.IV = Svc.Crypto.generateRandomIV(); @@ -214,9 +213,8 @@ CryptoWrapper.prototype = { throw "No ciphertext: nothing to decrypt?"; } - keyBundle = keyBundle || CollectionKeys.keyForCollection(this.collection); if (!keyBundle) { - throw new Error("Key bundle is null for " + this.collection + "/" + this.id); + throw new Error("A key bundle must be supplied to decrypt."); } // Authenticate the encrypted blob with the expected HMAC @@ -271,10 +269,6 @@ CryptoWrapper.prototype = { Utils.deferGetSet(CryptoWrapper, "payload", ["ciphertext", "IV", "hmac"]); Utils.deferGetSet(CryptoWrapper, "cleartext", "deleted"); -XPCOMUtils.defineLazyGetter(this, "CollectionKeys", function () { - return new CollectionKeyManager(); -}); - /** * Keeps track of mappings between collection names ('tabs') and KeyBundles. @@ -287,7 +281,7 @@ function CollectionKeyManager() { this._collections = {}; this._default = null; - this._log = Log4Moz.repository.getLogger("Sync.CollectionKeys"); + this._log = Log4Moz.repository.getLogger("Sync.CollectionKeyManager"); } // TODO: persist this locally as an Identity. Bug 610913. @@ -326,7 +320,7 @@ CollectionKeyManager.prototype = { }, clear: function clear() { - this._log.info("Clearing CollectionKeys..."); + this._log.info("Clearing collection keys..."); this.lastModified = 0; this._collections = {}; this._default = null; @@ -429,16 +423,16 @@ CollectionKeyManager.prototype = { let self = this; - this._log.info("Setting CollectionKeys contents. Our last modified: " + + this._log.info("Setting collection keys contents. Our last modified: " + this.lastModified + ", input modified: " + modified + "."); if (!payload) - throw "No payload in CollectionKeys.setContents()."; + throw "No payload in CollectionKeyManager.setContents()."; if (!payload.default) { this._log.warn("No downloaded default key: this should not occur."); this._log.warn("Not clearing local keys."); - throw "No default key in CollectionKeys.setContents(). Cannot proceed."; + throw "No default key in CollectionKeyManager.setContents(). Cannot proceed."; } // Process the incoming default key. diff --git a/services/sync/modules/service.js b/services/sync/modules/service.js index 46e9f9b520ba..f4fd2542237a 100644 --- a/services/sync/modules/service.js +++ b/services/sync/modules/service.js @@ -237,7 +237,7 @@ WeaveSvc.prototype = { let cryptoResp = cryptoKeys.fetch(this.resource(this.cryptoKeysURL)).response; // Save out the ciphertext for when we reupload. If there's a bug in - // CollectionKeys, this will prevent us from uploading junk. + // CollectionKeyManager, this will prevent us from uploading junk. let cipherText = cryptoKeys.ciphertext; if (!cryptoResp.success) { @@ -275,10 +275,8 @@ WeaveSvc.prototype = { handleFetchedKeys: function handleFetchedKeys(syncKey, cryptoKeys, skipReset) { // Don't want to wipe if we're just starting up! - // This is largely relevant because we don't persist - // CollectionKeys yet: Bug 610913. - let wasBlank = CollectionKeys.isClear; - let keysChanged = CollectionKeys.updateContents(syncKey, cryptoKeys); + let wasBlank = this.collectionKeys.isClear; + let keysChanged = this.collectionKeys.updateContents(syncKey, cryptoKeys); if (keysChanged && !wasBlank) { this._log.debug("Keys changed: " + JSON.stringify(keysChanged)); @@ -318,6 +316,8 @@ WeaveSvc.prototype = { this.identity = Status._authManager; + this.collectionKeys = new CollectionKeyManager(); + this.errorHandler = new ErrorHandler(this); this._log = Log4Moz.repository.getLogger("Sync.Service"); @@ -560,8 +560,8 @@ WeaveSvc.prototype = { this._log.info("Testing info/collections: " + JSON.stringify(infoCollections)); - if (CollectionKeys.updateNeeded(infoCollections)) { - this._log.info("CollectionKeys reports that a key update is needed."); + if (this.collectionKeys.updateNeeded(infoCollections)) { + this._log.info("collection keys reports that a key update is needed."); // Don't always set to CREDENTIALS_CHANGED -- we will probably take care of this. @@ -578,7 +578,7 @@ WeaveSvc.prototype = { return true; } else if (cryptoResp.status == 404) { - // On failure, ask CollectionKeys to generate new keys and upload them. + // On failure, ask to generate new keys and upload them. // Fall through to the behavior below. this._log.warn("Got 404 for crypto/keys, but 'crypto' in info/collections. Regenerating."); cryptoKeys = null; @@ -730,7 +730,7 @@ WeaveSvc.prototype = { generateNewSymmetricKeys: function generateNewSymmetricKeys() { this._log.info("Generating new keys WBO..."); - let wbo = CollectionKeys.generateNewKeysWBO(); + let wbo = this.collectionKeys.generateNewKeysWBO(); this._log.info("Encrypting new key bundle."); wbo.encrypt(this.identity.syncKeyBundle); @@ -818,7 +818,7 @@ WeaveSvc.prototype = { /* We need to re-encrypt everything, so reset. */ this.resetClient(); - CollectionKeys.clear(); + this.collectionKeys.clear(); /* Login and sync. This also generates new keys. */ this.sync(); @@ -859,7 +859,7 @@ WeaveSvc.prototype = { // Reset all engines and clear keys. this.resetClient(); - CollectionKeys.clear(); + this.collectionKeys.clear(); Status.resetBackoff(); // Reset Weave prefs. @@ -1074,7 +1074,7 @@ WeaveSvc.prototype = { this._log.info("Sync IDs differ. Local is " + this.syncID + ", remote is " + meta.payload.syncID); this.resetClient(); - CollectionKeys.clear(); + this.collectionKeys.clear(); this.syncID = meta.payload.syncID; this._log.debug("Clear cached values and take syncId: " + this.syncID); @@ -1236,7 +1236,7 @@ WeaveSvc.prototype = { _freshStart: function _freshStart() { this._log.info("Fresh start. Resetting client and considering key upgrade."); this.resetClient(); - CollectionKeys.clear(); + this.collectionKeys.clear(); this.upgradeSyncKey(this.syncID); // Wipe the server. diff --git a/services/sync/tests/unit/head_helpers.js b/services/sync/tests/unit/head_helpers.js index be18ef762659..c360087c86d1 100644 --- a/services/sync/tests/unit/head_helpers.js +++ b/services/sync/tests/unit/head_helpers.js @@ -273,10 +273,10 @@ function encryptPayload(cleartext) { hmac: fakeSHA256HMAC(cleartext, Utils.makeHMACKey(""))}; } -function generateNewKeys(collections) { - let wbo = CollectionKeys.generateNewKeysWBO(collections); +function generateNewKeys(collectionKeys, collections=null) { + let wbo = collectionKeys.generateNewKeysWBO(collections); let modified = new_timestamp(); - CollectionKeys.setContents(wbo.cleartext, modified); + collectionKeys.setContents(wbo.cleartext, modified); } /* diff --git a/services/sync/tests/unit/test_addons_engine.js b/services/sync/tests/unit/test_addons_engine.js index f4914da34f0f..0456994f0a4d 100644 --- a/services/sync/tests/unit/test_addons_engine.js +++ b/services/sync/tests/unit/test_addons_engine.js @@ -158,7 +158,7 @@ add_test(function test_disabled_install_semantics() { new SyncTestingInfrastructure(USER, PASSWORD, PASSPHRASE); - generateNewKeys(); + generateNewKeys(Service.collectionKeys); let contents = { meta: {global: {engines: {addons: {version: engine.version, diff --git a/services/sync/tests/unit/test_bookmark_engine.js b/services/sync/tests/unit/test_bookmark_engine.js index 3cfc0e31c011..8ba04a38020b 100644 --- a/services/sync/tests/unit/test_bookmark_engine.js +++ b/services/sync/tests/unit/test_bookmark_engine.js @@ -473,7 +473,7 @@ function run_test() { Log4Moz.repository.getLogger("Sync.Store.Bookmarks").level = Log4Moz.Level.Trace; Log4Moz.repository.getLogger("Sync.Tracker.Bookmarks").level = Log4Moz.Level.Trace; - generateNewKeys(); + generateNewKeys(Service.collectionKeys); run_next_test(); } diff --git a/services/sync/tests/unit/test_bookmark_record.js b/services/sync/tests/unit/test_bookmark_record.js index ff4a48f0ee55..bf56835ee8fd 100644 --- a/services/sync/tests/unit/test_bookmark_record.js +++ b/services/sync/tests/unit/test_bookmark_record.js @@ -17,7 +17,7 @@ function prepareBookmarkItem(collection, id) { function run_test() { Service.identity.username = "john@example.com"; Service.identity.syncKey = "abcdeabcdeabcdeabcdeabcdea"; - generateNewKeys(); + generateNewKeys(Service.collectionKeys); let keyBundle = Service.identity.syncKeyBundle; let log = Log4Moz.repository.getLogger("Test"); diff --git a/services/sync/tests/unit/test_bookmark_smart_bookmarks.js b/services/sync/tests/unit/test_bookmark_smart_bookmarks.js index 10c22f60b38b..421f9170fa12 100644 --- a/services/sync/tests/unit/test_bookmark_smart_bookmarks.js +++ b/services/sync/tests/unit/test_bookmark_smart_bookmarks.js @@ -230,7 +230,7 @@ function run_test() { initTestLogging("Trace"); Log4Moz.repository.getLogger("Sync.Engine.Bookmarks").level = Log4Moz.Level.Trace; - generateNewKeys(); + generateNewKeys(Service.collectionKeys); run_next_test(); } diff --git a/services/sync/tests/unit/test_clients_engine.js b/services/sync/tests/unit/test_clients_engine.js index 7929f1c6fe17..7f20d9e21c1e 100644 --- a/services/sync/tests/unit/test_clients_engine.js +++ b/services/sync/tests/unit/test_clients_engine.js @@ -49,8 +49,8 @@ add_test(function test_bad_hmac() { } function uploadNewKeys() { - generateNewKeys(); - let serverKeys = CollectionKeys.asWBO("crypto", "keys"); + generateNewKeys(Service.collectionKeys); + let serverKeys = Service.collectionKeys.asWBO("crypto", "keys"); serverKeys.encrypt(Service.identity.syncKeyBundle); do_check_true(serverKeys.upload(Service.resource(Service.cryptoKeysURL)).success); } @@ -61,7 +61,7 @@ add_test(function test_bad_hmac() { Service.clusterURL = TEST_CLUSTER_URL; Service.login("foo", "ilovejane", passphrase); - generateNewKeys(); + generateNewKeys(Service.collectionKeys); _("First sync, client record is uploaded"); do_check_eq(engine.lastRecordUpload, 0); @@ -78,8 +78,8 @@ add_test(function test_bad_hmac() { let oldLocalID = engine.localID; // Preserve to test for deletion! engine.localID = Utils.makeGUID(); engine.resetClient(); - generateNewKeys(); - let serverKeys = CollectionKeys.asWBO("crypto", "keys"); + generateNewKeys(Service.collectionKeys); + let serverKeys = Service.collectionKeys.asWBO("crypto", "keys"); serverKeys.encrypt(Service.identity.syncKeyBundle); do_check_true(serverKeys.upload(Service.resource(Service.cryptoKeysURL)).success); @@ -95,7 +95,7 @@ add_test(function test_bad_hmac() { Service.lastHMACEvent = 0; engine.localID = Utils.makeGUID(); engine.resetClient(); - generateNewKeys(); + generateNewKeys(Service.collectionKeys); deletedCollections = []; deletedItems = []; check_clients_count(1); @@ -131,8 +131,8 @@ add_test(function test_bad_hmac() { oldLocalID = engine.localID; // Preserve to test for deletion! engine.localID = Utils.makeGUID(); engine.resetClient(); - generateNewKeys(); - let oldKey = CollectionKeys.keyForCollection(); + generateNewKeys(Service.collectionKeys); + let oldKey = Service.collectionKeys.keyForCollection(); do_check_eq(deletedCollections.length, 0); do_check_eq(deletedItems.length, 0); @@ -140,7 +140,7 @@ add_test(function test_bad_hmac() { do_check_eq(deletedItems.length, 1); check_client_deleted(oldLocalID); check_clients_count(1); - let newKey = CollectionKeys.keyForCollection(); + let newKey = Service.collectionKeys.keyForCollection(); do_check_false(oldKey.equals(newKey)); } finally { @@ -169,7 +169,7 @@ add_test(function test_sync() { _("Ensure that Clients engine uploads a new client record once a week."); new SyncTestingInfrastructure(); - generateNewKeys(); + generateNewKeys(Service.collectionKeys); let contents = { meta: {global: {engines: {clients: {version: engine.version, @@ -409,7 +409,7 @@ add_test(function test_command_sync() { new SyncTestingInfrastructure(); engine._store.wipe(); - generateNewKeys(); + generateNewKeys(Service.collectionKeys); let contents = { meta: {global: {engines: {clients: {version: engine.version, diff --git a/services/sync/tests/unit/test_corrupt_keys.js b/services/sync/tests/unit/test_corrupt_keys.js index 552f053b5363..fdf36f791f7c 100644 --- a/services/sync/tests/unit/test_corrupt_keys.js +++ b/services/sync/tests/unit/test_corrupt_keys.js @@ -60,8 +60,8 @@ add_test(function test_locally_changed_keys() { Service.engineManager.register(HistoryEngine); function corrupt_local_keys() { - CollectionKeys._default.keyPair = [Svc.Crypto.generateRandomKey(), - Svc.Crypto.generateRandomKey()]; + Service.collectionKeys._default.keyPair = [Svc.Crypto.generateRandomKey(), + Svc.Crypto.generateRandomKey()]; } _("Setting meta."); @@ -75,8 +75,8 @@ add_test(function test_locally_changed_keys() { _("New meta/global: " + JSON.stringify(johndoe.collection("meta").wbo("global"))); // Upload keys. - generateNewKeys(); - let serverKeys = CollectionKeys.asWBO("crypto", "keys"); + generateNewKeys(Service.collectionKeys); + let serverKeys = Service.collectionKeys.asWBO("crypto", "keys"); serverKeys.encrypt(Service.identity.syncKeyBundle); do_check_true(serverKeys.upload(Service.resource(Service.cryptoKeysURL)).success); @@ -91,10 +91,10 @@ add_test(function test_locally_changed_keys() { _("Tabs modified: " + johndoe.modified("tabs")); do_check_true(johndoe.modified("tabs") > 0); - let coll_modified = CollectionKeys.lastModified; + let coll_modified = Service.collectionKeys.lastModified; // Let's create some server side history records. - let liveKeys = CollectionKeys.keyForCollection("history"); + let liveKeys = Service.collectionKeys.keyForCollection("history"); _("Keys now: " + liveKeys.keyPair); let visitType = Ci.nsINavHistoryService.TRANSITION_LINK; let history = johndoe.createCollection("history"); @@ -110,7 +110,7 @@ add_test(function test_locally_changed_keys() { sortindex: i, visits: [{date: (modified - 5) * 1000000, type: visitType}], deleted: false}; - w.encrypt(); + w.encrypt(liveKeys); let payload = {ciphertext: w.ciphertext, IV: w.IV, @@ -126,13 +126,13 @@ add_test(function test_locally_changed_keys() { let rec = new CryptoWrapper("history", "record-no--0"); rec.fetch(Service.resource(Service.storageURL + "history/record-no--0")); _(JSON.stringify(rec)); - do_check_true(!!rec.decrypt()); + do_check_true(!!rec.decrypt(liveKeys)); do_check_eq(hmacErrorCount, 0); // Fill local key cache with bad data. corrupt_local_keys(); - _("Keys now: " + CollectionKeys.keyForCollection("history").keyPair); + _("Keys now: " + Service.collectionKeys.keyForCollection("history").keyPair); do_check_eq(hmacErrorCount, 0); @@ -140,7 +140,7 @@ add_test(function test_locally_changed_keys() { // Now syncing should succeed, after one HMAC error. Service.sync(); do_check_eq(hmacErrorCount, 1); - _("Keys now: " + CollectionKeys.keyForCollection("history").keyPair); + _("Keys now: " + Service.collectionKeys.keyForCollection("history").keyPair); // And look! We downloaded history! let store = Service.engineManager.get("history")._store; @@ -165,7 +165,7 @@ add_test(function test_locally_changed_keys() { sortindex: i, visits: [{date: (modified - 5 ) * 1000000, type: visitType}], deleted: false}; - w.encrypt(); + w.encrypt(Service.collectionKeys.keyForCollection("history")); w.hmac = w.hmac.toUpperCase(); let payload = {ciphertext: w.ciphertext, @@ -183,7 +183,7 @@ add_test(function test_locally_changed_keys() { _("Syncing..."); Service.sync(); - _("Keys now: " + CollectionKeys.keyForCollection("history").keyPair); + _("Keys now: " + Service.collectionKeys.keyForCollection("history").keyPair); _("Server keys have been updated, and we skipped over 5 more HMAC errors without adjusting history."); do_check_true(johndoe.modified("crypto") > old_key_time); do_check_eq(hmacErrorCount, 6); diff --git a/services/sync/tests/unit/test_engine_abort.js b/services/sync/tests/unit/test_engine_abort.js index e91c7283feff..8f63e2c78032 100644 --- a/services/sync/tests/unit/test_engine_abort.js +++ b/services/sync/tests/unit/test_engine_abort.js @@ -8,7 +8,7 @@ Cu.import("resource://services-sync/util.js"); add_test(function test_processIncoming_abort() { _("An abort exception, raised in applyIncoming, will abort _processIncoming."); new SyncTestingInfrastructure(); - generateNewKeys(); + generateNewKeys(Service.collectionKeys); let engine = new RotaryEngine(Service); diff --git a/services/sync/tests/unit/test_errorhandler.js b/services/sync/tests/unit/test_errorhandler.js index 45c3156cb962..1376fde02e18 100644 --- a/services/sync/tests/unit/test_errorhandler.js +++ b/services/sync/tests/unit/test_errorhandler.js @@ -59,7 +59,7 @@ function generateCredentialsChangedFailure() { // Make sync fail due to changed credentials. We simply re-encrypt // the keys with a different Sync Key, without changing the local one. let newSyncKeyBundle = new SyncKeyBundle("johndoe", "23456234562345623456234562"); - let keys = CollectionKeys.asWBO(); + let keys = Service.collectionKeys.asWBO(); keys.encrypt(newSyncKeyBundle); keys.upload(Service.resource(Service.cryptoKeysURL)); } @@ -131,8 +131,8 @@ function setUp() { } function generateAndUploadKeys() { - generateNewKeys(); - let serverKeys = CollectionKeys.asWBO("crypto", "keys"); + generateNewKeys(Service.collectionKeys); + let serverKeys = Service.collectionKeys.asWBO("crypto", "keys"); serverKeys.encrypt(Service.identity.syncKeyBundle); return serverKeys.upload(Service.resource(Service.cryptoKeysURL)).success; } @@ -865,7 +865,7 @@ add_test(function test_crypto_keys_login_server_maintenance_error() { Service.clusterURL = TEST_MAINTENANCE_URL; // Force re-download of keys - CollectionKeys.clear(); + Service.collectionKeys.clear(); let backoffInterval; Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { @@ -999,7 +999,7 @@ add_test(function test_download_crypto_keys_login_prolonged_server_maintenance_e Service.serverURL = TEST_MAINTENANCE_URL; Service.clusterURL = TEST_MAINTENANCE_URL; // Force re-download of keys - CollectionKeys.clear(); + Service.collectionKeys.clear(); let backoffInterval; Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { @@ -1238,7 +1238,7 @@ add_test(function test_download_crypto_keys_login_syncAndReportErrors_server_mai Service.serverURL = TEST_MAINTENANCE_URL; Service.clusterURL = TEST_MAINTENANCE_URL; // Force re-download of keys - CollectionKeys.clear(); + Service.collectionKeys.clear(); let backoffInterval; Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { @@ -1477,7 +1477,7 @@ add_test(function test_download_crypto_keys_login_syncAndReportErrors_prolonged_ Service.serverURL = TEST_MAINTENANCE_URL; Service.clusterURL = TEST_MAINTENANCE_URL; // Force re-download of keys - CollectionKeys.clear(); + Service.collectionKeys.clear(); let backoffInterval; Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { diff --git a/services/sync/tests/unit/test_errorhandler_sync_checkServerError.js b/services/sync/tests/unit/test_errorhandler_sync_checkServerError.js index 495c67b9553f..d61666ca78c2 100644 --- a/services/sync/tests/unit/test_errorhandler_sync_checkServerError.js +++ b/services/sync/tests/unit/test_errorhandler_sync_checkServerError.js @@ -59,8 +59,8 @@ function setUp() { } function generateAndUploadKeys() { - generateNewKeys(); - let serverKeys = CollectionKeys.asWBO("crypto", "keys"); + generateNewKeys(Service.collectionKeys); + let serverKeys = Service.collectionKeys.asWBO("crypto", "keys"); serverKeys.encrypt(Service.identity.syncKeyBundle); let res = Service.resource("http://localhost:8080/1.1/johndoe/storage/crypto/keys"); return serverKeys.upload(res).success; diff --git a/services/sync/tests/unit/test_history_engine.js b/services/sync/tests/unit/test_history_engine.js index 74407466e997..1804baf9ace0 100644 --- a/services/sync/tests/unit/test_history_engine.js +++ b/services/sync/tests/unit/test_history_engine.js @@ -135,7 +135,7 @@ add_test(function test_processIncoming_mobile_history_batched() { }); function run_test() { - generateNewKeys(); + generateNewKeys(Service.collectionKeys); run_next_test(); } diff --git a/services/sync/tests/unit/test_hmac_error.js b/services/sync/tests/unit/test_hmac_error.js index 212a785399bb..9312e2c9b06d 100644 --- a/services/sync/tests/unit/test_hmac_error.js +++ b/services/sync/tests/unit/test_hmac_error.js @@ -83,7 +83,7 @@ add_test(function hmac_error_during_404() { _("Syncing."); Service.sync(); _("Partially resetting client, as if after a restart, and forcing redownload."); - CollectionKeys.clear(); + Service.collectionKeys.clear(); engine.lastSync = 0; // So that we redownload records. key404Counter = 1; _("---------------------------"); @@ -213,7 +213,7 @@ add_test(function hmac_error_during_node_reassignment() { Utils.nextTick(function() { _("Now a fresh sync will get no HMAC errors."); _("Partially resetting client, as if after a restart, and forcing redownload."); - CollectionKeys.clear(); + Service.collectionKeys.clear(); engine.lastSync = 0; hmacErrorCount = 0; diff --git a/services/sync/tests/unit/test_interval_triggers.js b/services/sync/tests/unit/test_interval_triggers.js index c8e11d5c5cea..67a933cfe683 100644 --- a/services/sync/tests/unit/test_interval_triggers.js +++ b/services/sync/tests/unit/test_interval_triggers.js @@ -38,8 +38,8 @@ function setUp() { Service.serverURL = TEST_SERVER_URL; Service.clusterURL = TEST_CLUSTER_URL; - generateNewKeys(); - let serverKeys = CollectionKeys.asWBO("crypto", "keys"); + generateNewKeys(Service.collectionKeys); + let serverKeys = Service.collectionKeys.asWBO("crypto", "keys"); serverKeys.encrypt(Service.identity.syncKeyBundle); return serverKeys.upload(Service.resource(Service.cryptoKeysURL)); } diff --git a/services/sync/tests/unit/test_keys.js b/services/sync/tests/unit/test_keys.js index 12f9b984bbcc..5d2a4e24e91a 100644 --- a/services/sync/tests/unit/test_keys.js +++ b/services/sync/tests/unit/test_keys.js @@ -5,6 +5,8 @@ Cu.import("resource://services-sync/constants.js"); Cu.import("resource://services-sync/identity.js"); Cu.import("resource://services-sync/keys.js"); +let collectionKeys = new CollectionKeyManager(); + function sha256HMAC(message, key) { let h = Utils.makeHMACHasher(Ci.nsICryptoHMAC.SHA256, key); return Utils.digestBytes(message, h); @@ -207,17 +209,17 @@ add_test(function test_collections_manager() { do_check_true(null == storage_keys.cleartext); do_check_true(null != storage_keys.ciphertext); - log.info("Updating CollectionKeys."); + log.info("Updating collection keys."); // updateContents decrypts the object, releasing the payload for us to use. // Returns true, because the default key has changed. - do_check_true(CollectionKeys.updateContents(keyBundle, storage_keys)); + do_check_true(collectionKeys.updateContents(keyBundle, storage_keys)); let payload = storage_keys.cleartext; - _("CK: " + JSON.stringify(CollectionKeys._collections)); + _("CK: " + JSON.stringify(collectionKeys._collections)); // Test that the CollectionKeyManager returns a similar WBO. - let wbo = CollectionKeys.asWBO("crypto", "keys"); + let wbo = collectionKeys.asWBO("crypto", "keys"); _("WBO: " + JSON.stringify(wbo)); _("WBO cleartext: " + JSON.stringify(wbo.cleartext)); @@ -226,17 +228,17 @@ add_test(function test_collections_manager() { do_check_eq(wbo.collection, "crypto"); do_check_eq(wbo.id, "keys"); do_check_eq(undefined, wbo.modified); - do_check_eq(CollectionKeys.lastModified, storage_keys.modified); + do_check_eq(collectionKeys.lastModified, storage_keys.modified); do_check_true(!!wbo.cleartext.default); do_check_keypair_eq(payload.default, wbo.cleartext.default); do_check_keypair_eq(payload.collections.bookmarks, wbo.cleartext.collections.bookmarks); - do_check_true('bookmarks' in CollectionKeys._collections); - do_check_false('tabs' in CollectionKeys._collections); + do_check_true('bookmarks' in collectionKeys._collections); + do_check_false('tabs' in collectionKeys._collections); _("Updating contents twice with the same data doesn't proceed."); storage_keys.encrypt(keyBundle); - do_check_false(CollectionKeys.updateContents(keyBundle, storage_keys)); + do_check_false(collectionKeys.updateContents(keyBundle, storage_keys)); /* * Test that we get the right keys out when we ask for @@ -244,7 +246,7 @@ add_test(function test_collections_manager() { */ let b1 = new BulkKeyBundle("bookmarks"); b1.keyPairB64 = [bookmarks_key64, bookmarks_hmac64]; - let b2 = CollectionKeys.keyForCollection("bookmarks"); + let b2 = collectionKeys.keyForCollection("bookmarks"); do_check_keypair_eq(b1.keyPair, b2.keyPair); // Check key equality. @@ -257,21 +259,21 @@ add_test(function test_collections_manager() { do_check_false(b1.equals(b2)); do_check_false(b2.equals(b1)); - b2 = CollectionKeys.keyForCollection(null); + b2 = collectionKeys.keyForCollection(null); do_check_keypair_eq(b1.keyPair, b2.keyPair); /* * Checking for update times. */ let info_collections = {}; - do_check_true(CollectionKeys.updateNeeded(info_collections)); + do_check_true(collectionKeys.updateNeeded(info_collections)); info_collections["crypto"] = 5000; - do_check_false(CollectionKeys.updateNeeded(info_collections)); + do_check_false(collectionKeys.updateNeeded(info_collections)); info_collections["crypto"] = 1 + (Date.now()/1000); // Add one in case computers are fast! - do_check_true(CollectionKeys.updateNeeded(info_collections)); + do_check_true(collectionKeys.updateNeeded(info_collections)); - CollectionKeys.lastModified = null; - do_check_true(CollectionKeys.updateNeeded({})); + collectionKeys.lastModified = null; + do_check_true(collectionKeys.updateNeeded({})); /* * Check _compareKeyBundleCollections. @@ -293,14 +295,14 @@ add_test(function test_collections_manager() { let coll5 = {"baz": k5, "bar": k2}; let coll6 = {}; - let d1 = CollectionKeys._compareKeyBundleCollections(coll1, coll2); // [] - let d2 = CollectionKeys._compareKeyBundleCollections(coll1, coll3); // ["bar"] - let d3 = CollectionKeys._compareKeyBundleCollections(coll3, coll2); // ["bar"] - let d4 = CollectionKeys._compareKeyBundleCollections(coll1, coll4); // ["bar", "foo"] - let d5 = CollectionKeys._compareKeyBundleCollections(coll5, coll2); // ["baz", "foo"] - let d6 = CollectionKeys._compareKeyBundleCollections(coll6, coll1); // ["bar", "foo"] - let d7 = CollectionKeys._compareKeyBundleCollections(coll5, coll5); // [] - let d8 = CollectionKeys._compareKeyBundleCollections(coll6, coll6); // [] + let d1 = collectionKeys._compareKeyBundleCollections(coll1, coll2); // [] + let d2 = collectionKeys._compareKeyBundleCollections(coll1, coll3); // ["bar"] + let d3 = collectionKeys._compareKeyBundleCollections(coll3, coll2); // ["bar"] + let d4 = collectionKeys._compareKeyBundleCollections(coll1, coll4); // ["bar", "foo"] + let d5 = collectionKeys._compareKeyBundleCollections(coll5, coll2); // ["baz", "foo"] + let d6 = collectionKeys._compareKeyBundleCollections(coll6, coll1); // ["bar", "foo"] + let d7 = collectionKeys._compareKeyBundleCollections(coll5, coll5); // [] + let d8 = collectionKeys._compareKeyBundleCollections(coll6, coll6); // [] do_check_true(d1.same); do_check_false(d2.same); diff --git a/services/sync/tests/unit/test_records_crypto.js b/services/sync/tests/unit/test_records_crypto.js index 5a6631c80b6d..e40a4da76caa 100644 --- a/services/sync/tests/unit/test_records_crypto.js +++ b/services/sync/tests/unit/test_records_crypto.js @@ -110,24 +110,24 @@ function run_test() { // Checking per-collection keys and default key handling. - generateNewKeys(); + generateNewKeys(Service.collectionKeys); let bu = "http://localhost:8080/storage/bookmarks/foo"; let bookmarkItem = prepareCryptoWrap("bookmarks", "foo"); - bookmarkItem.encrypt(); + bookmarkItem.encrypt(Service.collectionKeys.keyForCollection("bookmarks")); log.info("Ciphertext is " + bookmarkItem.ciphertext); do_check_true(bookmarkItem.ciphertext != null); log.info("Decrypting the record explicitly with the default key."); - do_check_eq(bookmarkItem.decrypt(CollectionKeys._default).stuff, "my payload here"); + do_check_eq(bookmarkItem.decrypt(Service.collectionKeys._default).stuff, "my payload here"); // Per-collection keys. // Generate a key for "bookmarks". - generateNewKeys(["bookmarks"]); + generateNewKeys(Service.collectionKeys, ["bookmarks"]); bookmarkItem = prepareCryptoWrap("bookmarks", "foo"); do_check_eq(bookmarkItem.collection, "bookmarks"); // Encrypt. This'll use the "bookmarks" encryption key, because we have a // special key for it. The same key will need to be used for decryption. - bookmarkItem.encrypt(); + bookmarkItem.encrypt(Service.collectionKeys.keyForCollection("bookmarks")); do_check_true(bookmarkItem.ciphertext != null); // Attempt to use the default key, because this is a collision that could @@ -135,7 +135,7 @@ function run_test() { // it's not the bookmarks key. let err; try { - bookmarkItem.decrypt(CollectionKeys._default); + bookmarkItem.decrypt(Service.collectionKeys._default); } catch (ex) { err = ex; } @@ -143,7 +143,7 @@ function run_test() { // Explicitly check that it's using the bookmarks key. // This should succeed. - do_check_eq(bookmarkItem.decrypt(CollectionKeys.keyForCollection("bookmarks")).stuff, + do_check_eq(bookmarkItem.decrypt(Service.collectionKeys.keyForCollection("bookmarks")).stuff, "my payload here"); log.info("Done!"); diff --git a/services/sync/tests/unit/test_service_detect_upgrade.js b/services/sync/tests/unit/test_service_detect_upgrade.js index d19cd8a20e29..7f7fc474ff06 100644 --- a/services/sync/tests/unit/test_service_detect_upgrade.js +++ b/services/sync/tests/unit/test_service_detect_upgrade.js @@ -100,7 +100,7 @@ add_test(function v4_upgrade() { // Now's a great time to test what happens when keys get replaced. _("Syncing afresh..."); Service.logout(); - CollectionKeys.clear(); + Service.collectionKeys.clear(); Service.serverURL = TEST_SERVER_URL; Service.clusterURL = TEST_CLUSTER_URL; meta_global.payload = JSON.stringify({"syncID": "foooooooooooooobbbbbbbbbbbb", @@ -133,7 +133,7 @@ add_test(function v4_upgrade() { function retrieve_and_compare_default(should_succeed) { let serverDefault = retrieve_server_default(); - let localDefault = CollectionKeys.keyForCollection().keyPairB64; + let localDefault = Service.collectionKeys.keyForCollection().keyPairB64; _("Retrieved keyBundle: " + JSON.stringify(serverDefault)); _("Local keyBundle: " + JSON.stringify(localDefault)); @@ -245,8 +245,8 @@ add_test(function v5_upgrade() { // -- keys decrypted with a different sync key, for example. _("Testing v4 -> v5 (or similar) upgrade."); function update_server_keys(syncKeyBundle, wboName, collWBO) { - generateNewKeys(); - serverKeys = CollectionKeys.asWBO("crypto", wboName); + generateNewKeys(Service.collectionKeys); + serverKeys = Service.collectionKeys.asWBO("crypto", wboName); serverKeys.encrypt(syncKeyBundle); let res = Service.resource(Service.storageURL + collWBO); do_check_true(serverKeys.upload(res).success); @@ -267,7 +267,7 @@ add_test(function v5_upgrade() { update_server_keys(badKeys, "bulk", "crypto/bulk"); // v5 _("Generating new keys."); - generateNewKeys(); + generateNewKeys(Service.collectionKeys); // Now sync and see what happens. It should be a version fail, not a crypto // fail. diff --git a/services/sync/tests/unit/test_service_sync_remoteSetup.js b/services/sync/tests/unit/test_service_sync_remoteSetup.js index 1d19153b15f2..4568d1a85af9 100644 --- a/services/sync/tests/unit/test_service_sync_remoteSetup.js +++ b/services/sync/tests/unit/test_service_sync_remoteSetup.js @@ -133,14 +133,14 @@ function run_test() { // changePassphrase wipes our keys, and they're regenerated on next sync. _("Checking changed passphrase."); - let existingDefault = CollectionKeys.keyForCollection(); + let existingDefault = Service.collectionKeys.keyForCollection(); let existingKeysPayload = keysWBO.payload; let newPassphrase = "bbbbbabcdeabcdeabcdeabcdea"; Service.changePassphrase(newPassphrase); _("Local key cache is full, but different."); - do_check_true(!!CollectionKeys._default); - do_check_false(CollectionKeys._default.equals(existingDefault)); + do_check_true(!!Service.collectionKeys._default); + do_check_false(Service.collectionKeys._default.equals(existingDefault)); _("Server has new keys."); do_check_true(!!keysWBO.payload); @@ -151,7 +151,7 @@ function run_test() { // Re-encrypt keys with a new random keybundle, and upload them to the // server, just as might happen with a second client. _("Attempting to screw up HMAC by re-encrypting keys."); - let keys = CollectionKeys.asWBO(); + let keys = Service.collectionKeys.asWBO(); let b = new BulkKeyBundle("hmacerror"); b.generateRandom(); collections.crypto = keys.modified = 100 + (Date.now()/1000); // Future modification time. diff --git a/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js b/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js index eb09a51ca4d2..2cafe302a08f 100644 --- a/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js +++ b/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js @@ -71,8 +71,8 @@ function setUp() { "abcdeabcdeabcdeabcdeabcdea"); // Ensure that the server has valid keys so that logging in will work and not // result in a server wipe, rendering many of these tests useless. - generateNewKeys(); - let serverKeys = CollectionKeys.asWBO("crypto", "keys"); + generateNewKeys(Service.collectionKeys); + let serverKeys = Service.collectionKeys.asWBO("crypto", "keys"); serverKeys.encrypt(Service.identity.syncKeyBundle); return serverKeys.upload(Service.resource(Service.cryptoKeysURL)).success; } @@ -254,7 +254,7 @@ add_test(function test_enabledRemotely() { // fresh start! try { _("Upload some keys to avoid a fresh start."); - let wbo = CollectionKeys.generateNewKeysWBO(); + let wbo = Service.collectionKeys.generateNewKeysWBO(); wbo.encrypt(Service.identity.syncKeyBundle); do_check_eq(200, wbo.upload(Service.resource(Service.cryptoKeysURL)).status); diff --git a/services/sync/tests/unit/test_service_wipeClient.js b/services/sync/tests/unit/test_service_wipeClient.js index a2e24be1ca1f..3046d926228a 100644 --- a/services/sync/tests/unit/test_service_wipeClient.js +++ b/services/sync/tests/unit/test_service_wipeClient.js @@ -69,10 +69,10 @@ add_test(function test_withEngineList() { }); add_test(function test_startOver_clears_keys() { - generateNewKeys(); - do_check_true(!!CollectionKeys.keyForCollection()); + generateNewKeys(Service.collectionKeys); + do_check_true(!!Service.collectionKeys.keyForCollection()); Service.startOver(); - do_check_false(!!CollectionKeys.keyForCollection()); + do_check_false(!!Service.collectionKeys.keyForCollection()); run_next_test(); }); diff --git a/services/sync/tests/unit/test_syncengine_sync.js b/services/sync/tests/unit/test_syncengine_sync.js index 8ee80678595c..5aa778607d21 100644 --- a/services/sync/tests/unit/test_syncengine_sync.js +++ b/services/sync/tests/unit/test_syncengine_sync.js @@ -50,7 +50,7 @@ function createServerAndConfigureClient() { } function run_test() { - generateNewKeys(); + generateNewKeys(Service.collectionKeys); Svc.Prefs.set("log.logger.engine.rotary", "Trace"); run_next_test(); } @@ -226,7 +226,7 @@ add_test(function test_processIncoming_createFromServer() { Service.clusterURL = TEST_CLUSTER_URL; Service.identity.username = "foo"; - generateNewKeys(); + generateNewKeys(Service.collectionKeys); // Some server records that will be downloaded let collection = new ServerCollection(); @@ -1329,7 +1329,7 @@ add_test(function test_uploadOutgoing_toEmptyServer() { "/1.1/foo/storage/rotary/flying": collection.wbo("flying").handler(), "/1.1/foo/storage/rotary/scotsman": collection.wbo("scotsman").handler() }); - generateNewKeys(); + generateNewKeys(Service.collectionKeys); let engine = makeRotaryEngine(); engine.lastSync = 123; // needs to be non-zero so that tracker is queried @@ -1636,7 +1636,7 @@ add_test(function test_sync_partialUpload() { let server = sync_httpd_setup({ "/1.1/foo/storage/rotary": collection.handler() }); - generateNewKeys(); + generateNewKeys(Service.collectionKeys); let engine = makeRotaryEngine(); engine.lastSync = 123; // needs to be non-zero so that tracker is queried @@ -1707,8 +1707,8 @@ add_test(function test_canDecrypt_noCryptoKeys() { Service.clusterURL = TEST_CLUSTER_URL; Service.identity.username = "foo"; - // Wipe CollectionKeys so we can test the desired scenario. - CollectionKeys.clear(); + // Wipe collection keys so we can test the desired scenario. + Service.collectionKeys.clear(); let collection = new ServerCollection(); collection._wbos.flying = new ServerWBO( @@ -1736,8 +1736,7 @@ add_test(function test_canDecrypt_true() { Service.clusterURL = TEST_CLUSTER_URL; Service.identity.username = "foo"; - // Set up CollectionKeys, as service.js does. - generateNewKeys(); + generateNewKeys(Service.collectionKeys); let collection = new ServerCollection(); collection._wbos.flying = new ServerWBO( diff --git a/services/sync/tests/unit/test_syncscheduler.js b/services/sync/tests/unit/test_syncscheduler.js index ea3c9631fc2b..b24993b10038 100644 --- a/services/sync/tests/unit/test_syncscheduler.js +++ b/services/sync/tests/unit/test_syncscheduler.js @@ -54,8 +54,8 @@ function setUp() { setBasicCredentials("johndoe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea"); Service.clusterURL = TEST_CLUSTER_URL; - generateNewKeys(); - let serverKeys = CollectionKeys.asWBO("crypto", "keys"); + generateNewKeys(Service.collectionKeys); + let serverKeys = Service.collectionKeys.asWBO("crypto", "keys"); serverKeys.encrypt(Service.identity.syncKeyBundle); return serverKeys.upload(Service.resource(Service.cryptoKeysURL)).success; } @@ -760,7 +760,7 @@ add_test(function test_sync_X_Weave_Backoff() { // sufficiently low. clientsEngine._store.create({id: "foo", cleartext: "bar"}); let rec = clientsEngine._store.createRecord("foo", "clients"); - rec.encrypt(); + rec.encrypt(Service.collectionKeys.keyForCollection("clients")); rec.upload(Service.resource(clientsEngine.engineURL + rec.id)); // Sync once to log in and get everything set up. Let's verify our initial @@ -817,7 +817,7 @@ add_test(function test_sync_503_Retry_After() { // sufficiently low. clientsEngine._store.create({id: "foo", cleartext: "bar"}); let rec = clientsEngine._store.createRecord("foo", "clients"); - rec.encrypt(); + rec.encrypt(Service.collectionKeys.keyForCollection("clients")); rec.upload(Service.resource(clientsEngine.engineURL + rec.id)); // Sync once to log in and get everything set up. Let's verify our initial