Bug 749957; r=rnewman
authorGregory Szorc <gps@mozilla.com>
Thu, 03 May 2012 14:25:33 -0700
changeset 92904 2db9df42823df471edd755e996267e7163bf09d5
parent 92903 c045085c0436cf1ef4c4a4447c54b24e7894501e
child 92905 cc91f155491b6cf8f83713bbe414e9a023027182
child 93472 3b0110befbe1cbd3b0a182e9f992525b7485ff4a
push id22603
push usergszorc@mozilla.com
push dateThu, 03 May 2012 21:26:05 +0000
treeherdermozilla-central@2db9df42823d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrnewman
bugs749957
milestone15.0a1
first release with
nightly linux32
2db9df42823d / 15.0a1 / 20120504030509 / files
nightly linux64
2db9df42823d / 15.0a1 / 20120504030509 / files
nightly mac
2db9df42823d / 15.0a1 / 20120504030509 / files
nightly win32
2db9df42823d / 15.0a1 / 20120504030509 / files
nightly win64
2db9df42823d / 15.0a1 / 20120504030509 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 749957; r=rnewman
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;