Bug 749957; r=rnewman, a=lsblakk
authorGregory Szorc <gps@mozilla.com>
Thu, 03 May 2012 14:25:33 -0700
changeset 95689 9ae9681dc9bdc914a4a7bb89ce62f243f3192fd9
parent 95688 88da07e9d9eadb6567b582f91f4ea20b5e359b19
child 95690 69e772363914496302586adc327e0f9a23601238
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrnewman, lsblakk
bugs749957
milestone14.0a2
Bug 749957; r=rnewman, a=lsblakk
services/sync/modules/identity.js
services/sync/modules/service.js
services/sync/tests/unit/test_identity_manager.js
--- a/services/sync/modules/identity.js
+++ b/services/sync/modules/identity.js
@@ -246,18 +246,18 @@ IdentityManager.prototype = {
 
     if (!this.username) {
       throw new Error("syncKey cannot be set before username.");
     }
 
     this._log.info("Sync Key being updated.");
     this._syncKey = value;
 
-    // Calling the getter has the side-effect of populating the object, which
-    // we desire.
+    // Clear any cached Sync Key Bundle and regenerate it.
+    this._syncKeyBundle = null;
     let bundle = this.syncKeyBundle;
 
     this._syncKeyUpdated = true;
   },
 
   /**
    * Obtain the active SyncKeyBundle.
    *
@@ -310,16 +310,22 @@ IdentityManager.prototype = {
     if (!this.basicPassword) {
       return LOGIN_FAILED_NO_PASSWORD;
     }
 
     if (!this.syncKey) {
       return LOGIN_FAILED_NO_PASSPHRASE;
     }
 
+    // If we have a Sync Key but no bundle, bundle creation failed, which
+    // implies a bad Sync Key.
+    if (!this.syncKeyBundle) {
+      return LOGIN_FAILED_INVALID_PASSPHRASE;
+    }
+
     return STATUS_OK;
   },
 
   /**
    * Persist credentials to password store.
    *
    * When credentials are updated, they are changed in memory only. This will
    * need to be called to save them to the underlying password store.
--- a/services/sync/modules/service.js
+++ b/services/sync/modules/service.js
@@ -549,27 +549,26 @@ WeaveSvc.prototype = {
   verifyAndFetchSymmetricKeys: function verifyAndFetchSymmetricKeys(infoResponse) {
 
     this._log.debug("Fetching and verifying -- or generating -- symmetric keys.");
 
     // Don't allow empty/missing passphrase.
     // Furthermore, we assume that our sync key is already upgraded,
     // and fail if that assumption is invalidated.
 
-    let syncKeyBundle = this._identity.syncKeyBundle;
-    if (!syncKeyBundle) {
-      this._log.error("No sync key: cannot fetch symmetric keys.");
+    if (!this._identity.syncKey) {
       Status.login = LOGIN_FAILED_NO_PASSPHRASE;
-      Status.sync = CREDENTIALS_CHANGED;             // For want of a better option.
+      Status.sync = CREDENTIALS_CHANGED;
       return false;
     }
 
-    // Not sure this validation is necessary now.
-    if (!Utils.isPassphrase(this._identity.syncKey)) {
-      this._log.warn("Sync key input is invalid: cannot fetch symmetric keys.");
+    let syncKeyBundle = this._identity.syncKeyBundle;
+    if (!syncKeyBundle) {
+      this._log.error("Sync Key Bundle not set. Invalid Sync Key?");
+
       Status.login = LOGIN_FAILED_INVALID_PASSPHRASE;
       Status.sync = CREDENTIALS_CHANGED;
       return false;
     }
 
     try {
       if (!infoResponse)
         infoResponse = this._fetchInfo();    // Will throw an exception on failure.
--- a/services/sync/tests/unit/test_identity_manager.js
+++ b/services/sync/tests/unit/test_identity_manager.js
@@ -175,16 +175,72 @@ add_test(function test_sync_key() {
   do_check_eq(im.syncKey, null);
   do_check_eq(im.syncKeyBundle, null);
 
   Identity.account = null;
 
   run_next_test();
 });
 
+add_test(function test_sync_key_changes() {
+  _("Ensure changes to Sync Key have appropriate side-effects.");
+
+  let im = new IdentityManager();
+  let sk1 = Utils.generatePassphrase();
+  let sk2 = Utils.generatePassphrase();
+
+  im.account = "johndoe";
+  do_check_eq(im.syncKey, null);
+  do_check_eq(im.syncKeyBundle, null);
+
+  im.syncKey = sk1;
+  do_check_neq(im.syncKeyBundle, null);
+
+  let ek1 = im.syncKeyBundle.encryptionKeyB64;
+  let hk1 = im.syncKeyBundle.hmacKeyB64;
+
+  // Change the Sync Key and ensure the Sync Key Bundle is updated.
+  im.syncKey = sk2;
+  let ek2 = im.syncKeyBundle.encryptionKeyB64;
+  let hk2 = im.syncKeyBundle.hmacKeyB64;
+
+  do_check_neq(ek1, ek2);
+  do_check_neq(hk1, hk2);
+
+  im.account = null;
+
+  run_next_test();
+});
+
+add_test(function test_current_auth_state() {
+  _("Ensure current auth state is reported properly.");
+
+  let im = new IdentityManager();
+  do_check_eq(im.currentAuthState, LOGIN_FAILED_NO_USERNAME);
+
+  im.account = "johndoe";
+  do_check_eq(im.currentAuthState, LOGIN_FAILED_NO_PASSWORD);
+
+  im.basicPassword = "ilovejane";
+  do_check_eq(im.currentAuthState, LOGIN_FAILED_NO_PASSPHRASE);
+
+  im.syncKey = "foobar";
+  do_check_eq(im.currentAuthState, LOGIN_FAILED_INVALID_PASSPHRASE);
+
+  im.syncKey = null;
+  do_check_eq(im.currentAuthState, LOGIN_FAILED_NO_PASSPHRASE);
+
+  im.syncKey = Utils.generatePassphrase();
+  do_check_eq(im.currentAuthState, STATUS_OK);
+
+  im.account = null;
+
+  run_next_test();
+});
+
 add_test(function test_sync_key_persistence() {
   _("Ensure Sync Key persistence works as expected.");
 
   Identity.account = "pseudojohn";
   Identity.password = "supersecret";
 
   let syncKey = Utils.generatePassphrase();
   Identity.syncKey = syncKey;