зеркало из https://github.com/mozilla/gecko-dev.git
Bug 730989 - Refactor identity and authentication in Sync; r=rnewman
This commit is contained in:
Родитель
4bf8f57ddf
Коммит
1f69a4ee14
|
@ -83,7 +83,7 @@ let gSyncAddDevice = {
|
|||
this.wizard.getButton("back").hidden = false;
|
||||
this.wizard.getButton("next").hidden = true;
|
||||
document.getElementById("weavePassphrase").value =
|
||||
Weave.Utils.hyphenatePassphrase(Weave.Service.passphrase);
|
||||
Weave.Utils.hyphenatePassphrase(Weave.Identity.syncKey);
|
||||
break;
|
||||
case DEVICE_CONNECTED_PAGE:
|
||||
this.wizard.canAdvance = true;
|
||||
|
@ -113,9 +113,9 @@ let gSyncAddDevice = {
|
|||
let self = this;
|
||||
let jpakeclient = this._jpakeclient = new Weave.JPAKEClient({
|
||||
onPaired: function onPaired() {
|
||||
let credentials = {account: Weave.Service.account,
|
||||
password: Weave.Service.password,
|
||||
synckey: Weave.Service.passphrase,
|
||||
let credentials = {account: Weave.Identity.account,
|
||||
password: Weave.Identity.basicPassword,
|
||||
synckey: Weave.Identity.syncKey,
|
||||
serverURL: Weave.Service.serverURL};
|
||||
jpakeclient.sendAndComplete(credentials);
|
||||
},
|
||||
|
|
|
@ -106,7 +106,7 @@ let Change = {
|
|||
document.getElementById("generatePassphraseButton").hidden = false;
|
||||
document.getElementById("passphraseBackupButtons").hidden = false;
|
||||
this._passphraseBox.setAttribute("readonly", "true");
|
||||
let pp = Weave.Service.passphrase;
|
||||
let pp = Weave.Identity.syncKey;
|
||||
if (Weave.Utils.isPassphrase(pp))
|
||||
pp = Weave.Utils.hyphenatePassphrase(pp);
|
||||
this._passphraseBox.value = pp;
|
||||
|
@ -193,7 +193,7 @@ let Change = {
|
|||
doChangePassphrase: function Change_doChangePassphrase() {
|
||||
let pp = Weave.Utils.normalizePassphrase(this._passphraseBox.value);
|
||||
if (this._updatingPassphrase) {
|
||||
Weave.Service.passphrase = pp;
|
||||
Weave.Identity.syncKey = pp;
|
||||
if (Weave.Service.login()) {
|
||||
this._updateStatus("change.recoverykey.success", "success");
|
||||
Weave.Service.persistLogin();
|
||||
|
@ -217,7 +217,7 @@ let Change = {
|
|||
|
||||
doChangePassword: function Change_doChangePassword() {
|
||||
if (this._currentPasswordInvalid) {
|
||||
Weave.Service.password = this._firstBox.value;
|
||||
Weave.Identity.basicPassword = this._firstBox.value;
|
||||
if (Weave.Service.login()) {
|
||||
this._updateStatus("change.password.status.success", "success");
|
||||
Weave.Service.persistLogin();
|
||||
|
|
|
@ -179,13 +179,13 @@ var gSyncSetup = {
|
|||
resetPassphrase: function resetPassphrase() {
|
||||
// Apply the existing form fields so that
|
||||
// Weave.Service.changePassphrase() has the necessary credentials.
|
||||
Weave.Service.account = document.getElementById("existingAccountName").value;
|
||||
Weave.Service.password = document.getElementById("existingPassword").value;
|
||||
Weave.Identity.account = document.getElementById("existingAccountName").value;
|
||||
Weave.Identity.basicPassword = document.getElementById("existingPassword").value;
|
||||
|
||||
// Generate a new passphrase so that Weave.Service.login() will
|
||||
// actually do something.
|
||||
let passphrase = Weave.Utils.generatePassphrase();
|
||||
Weave.Service.passphrase = passphrase;
|
||||
Weave.Identity.syncKey = passphrase;
|
||||
|
||||
// Only open the dialog if username + password are actually correct.
|
||||
Weave.Service.login();
|
||||
|
@ -210,7 +210,7 @@ var gSyncSetup = {
|
|||
|
||||
onResetPassphrase: function () {
|
||||
document.getElementById("existingPassphrase").value =
|
||||
Weave.Utils.hyphenatePassphrase(Weave.Service.passphrase);
|
||||
Weave.Utils.hyphenatePassphrase(Weave.Identity.syncKey);
|
||||
this.checkFields();
|
||||
this.wizard.advance();
|
||||
},
|
||||
|
@ -227,9 +227,9 @@ var gSyncSetup = {
|
|||
let send = function() {
|
||||
Services.obs.removeObserver("weave:service:sync:finish", send);
|
||||
Services.obs.removeObserver("weave:service:sync:error", send);
|
||||
let credentials = {account: Weave.Service.account,
|
||||
password: Weave.Service.password,
|
||||
synckey: Weave.Service.passphrase,
|
||||
let credentials = {account: Weave.Identity.account,
|
||||
password: Weave.Identity.basicPassword,
|
||||
synckey: Weave.Identity.syncKey,
|
||||
serverURL: Weave.Service.serverURL};
|
||||
this._jpakeclient.sendAndComplete(credentials);
|
||||
}.bind(this);
|
||||
|
@ -368,7 +368,7 @@ var gSyncSetup = {
|
|||
this._setFeedbackMessage(feedback, valid, str);
|
||||
this.status.email = valid;
|
||||
if (valid)
|
||||
Weave.Service.account = value;
|
||||
Weave.Identity.account = value;
|
||||
this.checkFields();
|
||||
},
|
||||
|
||||
|
@ -504,9 +504,9 @@ var gSyncSetup = {
|
|||
challenge, response);
|
||||
|
||||
if (error == null) {
|
||||
Weave.Service.account = email;
|
||||
Weave.Service.password = password;
|
||||
Weave.Service.passphrase = Weave.Utils.generatePassphrase();
|
||||
Weave.Identity.account = email;
|
||||
Weave.Identity.basicPassword = password;
|
||||
Weave.Identity.syncKey = Weave.Utils.generatePassphrase();
|
||||
this._handleNoScript(false);
|
||||
Weave.Svc.Prefs.set("firstSync", "newAccount");
|
||||
this.wizardFinish();
|
||||
|
@ -517,11 +517,12 @@ var gSyncSetup = {
|
|||
label.value = Weave.Utils.getErrorString(error);
|
||||
return false;
|
||||
case EXISTING_ACCOUNT_LOGIN_PAGE:
|
||||
Weave.Service.account = Weave.Utils.normalizeAccount(
|
||||
Weave.Identity.account = Weave.Utils.normalizeAccount(
|
||||
document.getElementById("existingAccountName").value);
|
||||
Weave.Service.password = document.getElementById("existingPassword").value;
|
||||
Weave.Identity.basicPssword =
|
||||
document.getElementById("existingPassword").value;
|
||||
let pp = document.getElementById("existingPassphrase").value;
|
||||
Weave.Service.passphrase = Weave.Utils.normalizePassphrase(pp);
|
||||
Weave.Identity.syncKey = Weave.Utils.normalizePassphrase(pp);
|
||||
if (Weave.Service.login()) {
|
||||
this.wizardFinish();
|
||||
}
|
||||
|
@ -700,9 +701,9 @@ var gSyncSetup = {
|
|||
onPairingStart: function onPairingStart() {},
|
||||
|
||||
onComplete: function onComplete(credentials) {
|
||||
Weave.Service.account = credentials.account;
|
||||
Weave.Service.password = credentials.password;
|
||||
Weave.Service.passphrase = credentials.synckey;
|
||||
Weave.Identity.account = credentials.account;
|
||||
Weave.Identity.basicPassword = credentials.password;
|
||||
Weave.Identity.syncKey = credentials.synckey;
|
||||
Weave.Service.serverURL = credentials.serverURL;
|
||||
gSyncSetup.wizardFinish();
|
||||
},
|
||||
|
|
|
@ -227,13 +227,13 @@ let gSyncUtils = {
|
|||
|
||||
if (!el2)
|
||||
valid = val1.length >= Weave.MIN_PASS_LENGTH;
|
||||
else if (val1 && val1 == Weave.Service.username)
|
||||
else if (val1 && val1 == Weave.Identity.username)
|
||||
error = "change.password.pwSameAsUsername";
|
||||
else if (val1 && val1 == Weave.Service.account)
|
||||
else if (val1 && val1 == Weave.Identity.account)
|
||||
error = "change.password.pwSameAsEmail";
|
||||
else if (val1 && val1 == Weave.Service.password)
|
||||
else if (val1 && val1 == Weave.Identity.basicPassword)
|
||||
error = "change.password.pwSameAsPassword";
|
||||
else if (val1 && val1 == Weave.Service.passphrase)
|
||||
else if (val1 && val1 == Weave.Identity.syncKey)
|
||||
error = "change.password.pwSameAsRecoveryKey";
|
||||
else if (val1 && val2) {
|
||||
if (val1 == val2 && val1.length >= Weave.MIN_PASS_LENGTH)
|
||||
|
|
|
@ -573,7 +573,7 @@ SyncEngine.prototype = {
|
|||
applyIncomingBatchSize: DEFAULT_STORE_BATCH_SIZE,
|
||||
|
||||
get storageURL() Svc.Prefs.get("clusterURL") + SYNC_API_VERSION +
|
||||
"/" + ID.get("WeaveID").username + "/storage/",
|
||||
"/" + Identity.username + "/storage/",
|
||||
|
||||
get engineURL() this.storageURL + this.name,
|
||||
|
||||
|
|
|
@ -1,143 +1,491 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Bookmarks Sync.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dan Mills <thunder@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const EXPORTED_SYMBOLS = ['Identity', 'ID'];
|
||||
"use strict";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
const EXPORTED_SYMBOLS = ["Identity", "IdentityManager"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/keys.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
// Avoid circular import.
|
||||
__defineGetter__("Service", function() {
|
||||
delete this.Service;
|
||||
Cu.import("resource://services-sync/service.js", this);
|
||||
return this.Service;
|
||||
XPCOMUtils.defineLazyGetter(this, "Identity", function() {
|
||||
return new IdentityManager();
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "ID", function () {
|
||||
return new IDManager();
|
||||
});
|
||||
|
||||
// For storing identities we'll use throughout Weave
|
||||
function IDManager() {
|
||||
this._ids = {};
|
||||
}
|
||||
IDManager.prototype = {
|
||||
get: function IDMgr_get(name) {
|
||||
if (name in this._ids)
|
||||
return this._ids[name];
|
||||
return null;
|
||||
},
|
||||
set: function IDMgr_set(name, id) {
|
||||
this._ids[name] = id;
|
||||
return id;
|
||||
},
|
||||
del: function IDMgr_del(name) {
|
||||
delete this._ids[name];
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Identity
|
||||
* These objects hold a realm, username, and password
|
||||
* They can hold a password in memory, but will try to fetch it from
|
||||
* the password manager if it's not set.
|
||||
* FIXME: need to rethink this stuff as part of a bigger identity mgmt framework
|
||||
/**
|
||||
* Manages identity and authentication for Sync.
|
||||
*
|
||||
* The following entities are managed:
|
||||
*
|
||||
* account - The main Sync/services account. This is typically an email
|
||||
* address.
|
||||
* username - A normalized version of your account. This is what's
|
||||
* transmitted to the server.
|
||||
* basic password - UTF-8 password used for authenticating when using HTTP
|
||||
* basic authentication.
|
||||
* sync key - The main encryption key used by Sync.
|
||||
* sync key bundle - A representation of your sync key.
|
||||
*
|
||||
* An instance of this type is lazily instantiated under Weave.Identity. It is
|
||||
* and should be treated as a global variable. The reason is that saved changes
|
||||
* are stored in preferences and the password manager. So, if you created
|
||||
* multiple instances, they would just step on each other's state.
|
||||
*
|
||||
* When changes are made to entities that are stored in the password manager
|
||||
* (basic password, sync key), those changes are merely staged. To commit them
|
||||
* to the password manager, you'll need to call persistCredentials().
|
||||
*
|
||||
* This type also manages authenticating Sync's network requests. Sync's
|
||||
* network code calls into getRESTRequestAuthenticator and
|
||||
* getResourceAuthenticator (depending on the network layer being used). Each
|
||||
* returns a function which can be used to add authentication information to an
|
||||
* outgoing request.
|
||||
*
|
||||
* In theory, this type supports arbitrary identity and authentication
|
||||
* mechanisms. You can add support for them by monkeypatching the global
|
||||
* instance of this type. Specifically, you'll need to redefine the
|
||||
* aforementioned network code functions to do whatever your authentication
|
||||
* mechanism needs them to do. In addition, you may wish to install custom
|
||||
* functions to support your API. Although, that is certainly not required.
|
||||
* If you do monkeypatch, please be advised that Sync expects the core
|
||||
* attributes to have values. You will need to carry at least account and
|
||||
* username forward. If you do not wish to support one of the built-in
|
||||
* authentication mechanisms, you'll probably want to redefine currentAuthState
|
||||
* and any other function that involves the built-in functionality.
|
||||
*/
|
||||
function IdentityManager() {
|
||||
this._log = Log4Moz.repository.getLogger("Sync.Identity");
|
||||
this._log.Level = Log4Moz.Level[Svc.Prefs.get("log.logger.identity")];
|
||||
|
||||
function Identity(realm, username, password) {
|
||||
this.realm = realm;
|
||||
this.username = username;
|
||||
this._password = password;
|
||||
if (password)
|
||||
this._passwordUTF8 = Utils.encodeUTF8(password);
|
||||
this._basicPassword = null;
|
||||
this._basicPasswordAllowLookup = true;
|
||||
this._basicPasswordUpdated = false;
|
||||
this._syncKey = null;
|
||||
this._syncKeyAllowLookup = true;
|
||||
this._syncKeySet = false;
|
||||
this._syncKeyBundle = null;
|
||||
}
|
||||
Identity.prototype = {
|
||||
get password() {
|
||||
// Look up the password then cache it
|
||||
if (this._password == null)
|
||||
for each (let login in this._logins)
|
||||
if (login.username.toLowerCase() == this.username) {
|
||||
this._password = login.password;
|
||||
this._passwordUTF8 = Utils.encodeUTF8(login.password);
|
||||
}
|
||||
return this._password;
|
||||
IdentityManager.prototype = {
|
||||
_log: null,
|
||||
|
||||
_basicPassword: null,
|
||||
_basicPasswordAllowLookup: true,
|
||||
_basicPasswordUpdated: false,
|
||||
|
||||
_syncKey: null,
|
||||
_syncKeyAllowLookup: true,
|
||||
_syncKeySet: false,
|
||||
|
||||
_syncKeyBundle: null,
|
||||
|
||||
get account() {
|
||||
return Svc.Prefs.get("account", this.username);
|
||||
},
|
||||
|
||||
set password(value) {
|
||||
this._password = value;
|
||||
this._passwordUTF8 = Utils.encodeUTF8(value);
|
||||
},
|
||||
|
||||
get passwordUTF8() {
|
||||
if (!this._passwordUTF8)
|
||||
this.password; // invoke password getter
|
||||
return this._passwordUTF8;
|
||||
},
|
||||
|
||||
persist: function persist() {
|
||||
// Clean up any existing passwords unless it's what we're persisting
|
||||
let exists = false;
|
||||
for each (let login in this._logins) {
|
||||
if (login.username == this.username && login.password == this._password)
|
||||
exists = true;
|
||||
else
|
||||
Services.logins.removeLogin(login);
|
||||
/**
|
||||
* Sets the active account name.
|
||||
*
|
||||
* This should almost always be called in favor of setting username, as
|
||||
* username is derived from account.
|
||||
*
|
||||
* Changing the account name has the side-effect of wiping out stored
|
||||
* credentials. Keep in mind that persistCredentials() will need to be called
|
||||
* to flush the changes to disk.
|
||||
*
|
||||
* Set this value to null to clear out identity information.
|
||||
*/
|
||||
set account(value) {
|
||||
if (value) {
|
||||
value = value.toLowerCase();
|
||||
Svc.Prefs.set("account", value);
|
||||
} else {
|
||||
Svc.Prefs.reset("account");
|
||||
}
|
||||
|
||||
// No need to create the login after clearing out the other ones
|
||||
let log = Log4Moz.repository.getLogger("Sync.Identity");
|
||||
if (exists) {
|
||||
log.trace("Skipping persist: " + this.realm + " for " + this.username);
|
||||
this.username = this.usernameFromAccount(value);
|
||||
},
|
||||
|
||||
get username() {
|
||||
return Svc.Prefs.get("username", null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the username value.
|
||||
*
|
||||
* Changing the username has the side-effect of wiping credentials.
|
||||
*/
|
||||
set username(value) {
|
||||
if (value) {
|
||||
value = value.toLowerCase();
|
||||
|
||||
if (value == this.username) {
|
||||
return;
|
||||
}
|
||||
|
||||
Svc.Prefs.set("username", value);
|
||||
} else {
|
||||
Svc.Prefs.reset("username");
|
||||
}
|
||||
|
||||
// If we change the username, we interpret this as a major change event
|
||||
// and wipe out the credentials.
|
||||
this._log.info("Username changed. Removing stored credentials.");
|
||||
this.basicPassword = null;
|
||||
this.syncKey = null;
|
||||
// syncKeyBundle cleared as a result of setting syncKey.
|
||||
},
|
||||
|
||||
/**
|
||||
* Obtains the HTTP Basic auth password.
|
||||
*
|
||||
* Returns a string if set or null if it is not set.
|
||||
*/
|
||||
get basicPassword() {
|
||||
if (this._basicPasswordAllowLookup) {
|
||||
// We need a username to find the credentials.
|
||||
let username = this.username;
|
||||
if (!username) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for each (let login in this._getLogins(PWDMGR_PASSWORD_REALM)) {
|
||||
if (login.username.toLowerCase() == username) {
|
||||
// It should already be UTF-8 encoded, but we don't take any chances.
|
||||
this._basicPassword = Utils.encodeUTF8(login.password);
|
||||
}
|
||||
}
|
||||
|
||||
this._basicPasswordAllowLookup = false;
|
||||
}
|
||||
|
||||
return this._basicPassword;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the HTTP basic password to use.
|
||||
*
|
||||
* Changes will not persist unless persistSyncCredentials() is called.
|
||||
*/
|
||||
set basicPassword(value) {
|
||||
// Wiping out value.
|
||||
if (!value) {
|
||||
this._log.info("Basic password has no value. Removing.");
|
||||
this._basicPassword = null;
|
||||
this._basicPasswordUpdated = true;
|
||||
this._basicPasswordAllowLookup = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the new username/password
|
||||
log.trace("Persisting " + this.realm + " for " + this.username);
|
||||
let nsLoginInfo = new Components.Constructor(
|
||||
"@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo, "init");
|
||||
let newLogin = new nsLoginInfo(PWDMGR_HOST, null, this.realm,
|
||||
this.username, this.password, "", "");
|
||||
Services.logins.addLogin(newLogin);
|
||||
let username = this.username;
|
||||
if (!username) {
|
||||
throw new Error("basicPassword cannot be set before username.");
|
||||
}
|
||||
|
||||
this._log.info("Basic password being updated.");
|
||||
this._basicPassword = Utils.encodeUTF8(value);
|
||||
this._basicPasswordUpdated = true;
|
||||
},
|
||||
|
||||
get _logins() Services.logins.findLogins({}, PWDMGR_HOST, null, this.realm)
|
||||
/**
|
||||
* Obtain the Sync Key.
|
||||
*
|
||||
* This returns a 26 character "friendly" Base32 encoded string on success or
|
||||
* null if no Sync Key could be found.
|
||||
*
|
||||
* If the Sync Key hasn't been set in this session, this will look in the
|
||||
* password manager for the sync key.
|
||||
*/
|
||||
get syncKey() {
|
||||
if (this._syncKeyAllowLookup) {
|
||||
let username = this.username;
|
||||
if (!username) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for each (let login in this._getLogins(PWDMGR_PASSPHRASE_REALM)) {
|
||||
if (login.username.toLowerCase() == username) {
|
||||
this._syncKey = login.password;
|
||||
}
|
||||
}
|
||||
|
||||
this._syncKeyAllowLookup = false;
|
||||
}
|
||||
|
||||
return this._syncKey;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the active Sync Key.
|
||||
*
|
||||
* If being set to null, the Sync Key and its derived SyncKeyBundle are
|
||||
* removed. However, the Sync Key won't be deleted from the password manager
|
||||
* until persistSyncCredentials() is called.
|
||||
*
|
||||
* If a value is provided, it should be a 26 or 32 character "friendly"
|
||||
* Base32 string for which Utils.isPassphrase() returns true.
|
||||
*
|
||||
* A side-effect of setting the Sync Key is that a SyncKeyBundle is
|
||||
* generated. For historical reasons, this will silently error out if the
|
||||
* value is not a proper Sync Key (!Utils.isPassphrase()). This should be
|
||||
* fixed in the future (once service.js is more sane) to throw if the passed
|
||||
* value is not valid.
|
||||
*/
|
||||
set syncKey(value) {
|
||||
if (!value) {
|
||||
this._log.info("Sync Key has no value. Deleting.");
|
||||
this._syncKey = null;
|
||||
this._syncKeyBundle = null;
|
||||
this._syncKeyUpdated = true;
|
||||
return;
|
||||
}
|
||||
|
||||
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.
|
||||
let bundle = this.syncKeyBundle;
|
||||
|
||||
this._syncKeyUpdated = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Obtain the active SyncKeyBundle.
|
||||
*
|
||||
* This returns a SyncKeyBundle representing a key pair derived from the
|
||||
* Sync Key on success. If no Sync Key is present or if the Sync Key is not
|
||||
* valid, this returns null.
|
||||
*
|
||||
* The SyncKeyBundle should be treated as immutable.
|
||||
*/
|
||||
get syncKeyBundle() {
|
||||
// We can't obtain a bundle without a username set.
|
||||
if (!this.username) {
|
||||
this._log.warn("Attempted to obtain Sync Key Bundle with no username set!");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!this.syncKey) {
|
||||
this._log.warn("Attempted to obtain Sync Key Bundle with no Sync Key " +
|
||||
"set!");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!this._syncKeyBundle) {
|
||||
try {
|
||||
this._syncKeyBundle = new SyncKeyBundle(this.username, this.syncKey);
|
||||
} catch (ex) {
|
||||
this._log.warn(Utils.exceptionStr(ex));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return this._syncKeyBundle;
|
||||
},
|
||||
|
||||
/**
|
||||
* The current state of the auth credentials.
|
||||
*
|
||||
* This essentially validates that enough credentials are available to use
|
||||
* Sync.
|
||||
*/
|
||||
get currentAuthState() {
|
||||
if (!this.username) {
|
||||
return LOGIN_FAILED_NO_USERNAME;
|
||||
}
|
||||
|
||||
if (Utils.mpLocked()) {
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
if (!this.basicPassword) {
|
||||
return LOGIN_FAILED_NO_PASSWORD;
|
||||
}
|
||||
|
||||
if (!this.syncKey) {
|
||||
return LOGIN_FAILED_NO_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.
|
||||
*
|
||||
* If the password store is locked (e.g. if the master password hasn't been
|
||||
* entered), this could throw an exception.
|
||||
*/
|
||||
persistCredentials: function persistCredentials() {
|
||||
if (this._basicPasswordUpdated) {
|
||||
if (this._basicPassword) {
|
||||
this._setLogin(PWDMGR_PASSWORD_REALM, this.username,
|
||||
this._basicPassword);
|
||||
} else {
|
||||
for each (let login in this._getLogins(PWDMGR_PASSWORD_REALM)) {
|
||||
Services.logins.removeLogin(login);
|
||||
}
|
||||
}
|
||||
|
||||
this._basicPasswordUpdated = false;
|
||||
}
|
||||
|
||||
if (this._syncKeyUpdated) {
|
||||
if (this._syncKey) {
|
||||
this._setLogin(PWDMGR_PASSPHRASE_REALM, this.username, this._syncKey);
|
||||
} else {
|
||||
for each (let login in this._getLogins(PWDMGR_PASSPHRASE_REALM)) {
|
||||
Services.logins.removeLogin(login);
|
||||
}
|
||||
}
|
||||
|
||||
this._syncKeyUpdated = false;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes the Sync Key from the system.
|
||||
*/
|
||||
deleteSyncKey: function deleteSyncKey() {
|
||||
this.syncKey = null;
|
||||
this.persistCredentials();
|
||||
},
|
||||
|
||||
hasBasicCredentials: function hasBasicCredentials() {
|
||||
// Because JavaScript.
|
||||
return this.username && this.basicPassword && true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Obtains the array of basic logins from nsiPasswordManager.
|
||||
*/
|
||||
_getLogins: function _getLogins(realm) {
|
||||
return Services.logins.findLogins({}, PWDMGR_HOST, null, realm);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set a login in the password manager.
|
||||
*
|
||||
* This has the side-effect of deleting any other logins for the specified
|
||||
* realm.
|
||||
*/
|
||||
_setLogin: function _setLogin(realm, username, password) {
|
||||
let exists = false;
|
||||
for each (let login in this._getLogins(realm)) {
|
||||
if (login.username == username && login.password == password) {
|
||||
exists = true;
|
||||
} else {
|
||||
this._log.debug("Pruning old login for " + username + " from " + realm);
|
||||
Services.logins.removeLogin(login);
|
||||
}
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._log.debug("Updating saved password for " + username + " in " +
|
||||
realm);
|
||||
|
||||
let loginInfo = new Components.Constructor(
|
||||
"@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo, "init");
|
||||
let login = new loginInfo(PWDMGR_HOST, null, realm, username,
|
||||
password, "", "");
|
||||
Services.logins.addLogin(login);
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes Sync credentials from the password manager.
|
||||
*/
|
||||
deleteSyncCredentials: function deleteSyncCredentials() {
|
||||
let logins = Services.logins.findLogins({}, PWDMGR_HOST, "", "");
|
||||
for each (let login in logins) {
|
||||
Services.logins.removeLogin(login);
|
||||
}
|
||||
|
||||
// Wait until after store is updated in case it fails.
|
||||
this._basicPassword = null;
|
||||
this._basicPasswordAllowLookup = true;
|
||||
this._basicPasswordUpdated = false;
|
||||
|
||||
this._syncKey = null;
|
||||
// this._syncKeyBundle is nullified as part of _syncKey setter.
|
||||
this._syncKeyAllowLookup = true;
|
||||
this._syncKeyUpdated = false;
|
||||
},
|
||||
|
||||
usernameFromAccount: function usernameFromAccount(value) {
|
||||
// If we encounter characters not allowed by the API (as found for
|
||||
// instance in an email address), hash the value.
|
||||
if (value && value.match(/[^A-Z0-9._-]/i)) {
|
||||
return Utils.sha1Base32(value.toLowerCase()).toLowerCase();
|
||||
}
|
||||
|
||||
return value ? value.toLowerCase() : value;
|
||||
},
|
||||
|
||||
/**
|
||||
* Obtain a function to be used for adding auth to Resource HTTP requests.
|
||||
*/
|
||||
getResourceAuthenticator: function getResourceAuthenticator() {
|
||||
if (this.hasBasicCredentials()) {
|
||||
return this._onResourceRequestBasic.bind(this);
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper method to return an authenticator for basic Resource requests.
|
||||
*/
|
||||
getBasicResourceAuthenticator:
|
||||
function getBasicResourceAuthenticator(username, password) {
|
||||
|
||||
return function basicAuthenticator(resource) {
|
||||
let value = "Basic " + btoa(username + ":" + password);
|
||||
return {headers: {authorization: value}};
|
||||
};
|
||||
},
|
||||
|
||||
_onResourceRequestBasic: function _onResourceRequestBasic(resource) {
|
||||
let value = "Basic " + btoa(this.username + ":" + this.basicPassword);
|
||||
return {headers: {authorization: value}};
|
||||
},
|
||||
|
||||
_onResourceRequestMAC: function _onResourceRequestMAC(resource, method) {
|
||||
// TODO Get identifier and key from somewhere.
|
||||
let identifier;
|
||||
let key;
|
||||
let result = Utils.computeHTTPMACSHA1(identifier, key, method, resource.uri);
|
||||
|
||||
return {headers: {authorization: result.header}};
|
||||
},
|
||||
|
||||
/**
|
||||
* Obtain a function to be used for adding auth to RESTRequest instances.
|
||||
*/
|
||||
getRESTRequestAuthenticator: function getRESTRequestAuthenticator() {
|
||||
if (this.hasBasicCredentials()) {
|
||||
return this.onRESTRequestBasic.bind(this);
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
onRESTRequestBasic: function onRESTRequestBasic(request) {
|
||||
let up = this.username + ":" + this.basicPassword;
|
||||
request.setHeader("authorization", "Basic " + btoa(up));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,214 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const EXPORTED_SYMBOLS = [
|
||||
"BulkKeyBundle",
|
||||
"SyncKeyBundle"
|
||||
];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
/**
|
||||
* Represents a pair of keys.
|
||||
*
|
||||
* Each key stored in a key bundle is 256 bits. One key is used for symmetric
|
||||
* encryption. The other is used for HMAC.
|
||||
*
|
||||
* A KeyBundle by itself is just an anonymous pair of keys. Other types
|
||||
* deriving from this one add semantics, such as associated collections or
|
||||
* generating a key bundle via HKDF from another key.
|
||||
*/
|
||||
function KeyBundle() {
|
||||
this._encrypt = null;
|
||||
this._encryptB64 = null;
|
||||
this._hmac = null;
|
||||
this._hmacB64 = null;
|
||||
this._hmacObj = null;
|
||||
this._sha256HMACHasher = null;
|
||||
}
|
||||
KeyBundle.prototype = {
|
||||
_encrypt: null,
|
||||
_encryptB64: null,
|
||||
_hmac: null,
|
||||
_hmacB64: null,
|
||||
_hmacObj: null,
|
||||
_sha256HMACHasher: null,
|
||||
|
||||
equals: function equals(bundle) {
|
||||
return bundle &&
|
||||
(bundle.hmacKey == this.hmacKey) &&
|
||||
(bundle.encryptionKey == this.encryptionKey);
|
||||
},
|
||||
|
||||
/*
|
||||
* Accessors for the two keys.
|
||||
*/
|
||||
get encryptionKey() {
|
||||
return this._encrypt;
|
||||
},
|
||||
|
||||
set encryptionKey(value) {
|
||||
if (!value || typeof value != "string") {
|
||||
throw new Error("Encryption key can only be set to string values.");
|
||||
}
|
||||
|
||||
if (value.length < 16) {
|
||||
throw new Error("Encryption key must be at least 128 bits long.");
|
||||
}
|
||||
|
||||
this._encrypt = value;
|
||||
this._encryptB64 = btoa(value);
|
||||
},
|
||||
|
||||
get encryptionKeyB64() {
|
||||
return this._encryptB64;
|
||||
},
|
||||
|
||||
get hmacKey() {
|
||||
return this._hmac;
|
||||
},
|
||||
|
||||
set hmacKey(value) {
|
||||
if (!value || typeof value != "string") {
|
||||
throw new Error("HMAC key can only be set to string values.");
|
||||
}
|
||||
|
||||
if (value.length < 16) {
|
||||
throw new Error("HMAC key must be at least 128 bits long.");
|
||||
}
|
||||
|
||||
this._hmac = value;
|
||||
this._hmacB64 = btoa(value);
|
||||
this._hmacObj = value ? Utils.makeHMACKey(value) : null;
|
||||
this._sha256HMACHasher = value ? Utils.makeHMACHasher(
|
||||
Ci.nsICryptoHMAC.SHA256, this._hmacObj) : null;
|
||||
},
|
||||
|
||||
get hmacKeyB64() {
|
||||
return this._hmacB64;
|
||||
},
|
||||
|
||||
get hmacKeyObject() {
|
||||
return this._hmacObj;
|
||||
},
|
||||
|
||||
get sha256HMACHasher() {
|
||||
return this._sha256HMACHasher;
|
||||
},
|
||||
|
||||
/**
|
||||
* Populate this key pair with 2 new, randomly generated keys.
|
||||
*/
|
||||
generateRandom: function generateRandom() {
|
||||
let generatedHMAC = Svc.Crypto.generateRandomKey();
|
||||
let generatedEncr = Svc.Crypto.generateRandomKey();
|
||||
this.keyPairB64 = [generatedEncr, generatedHMAC];
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a KeyBundle associated with a collection.
|
||||
*
|
||||
* This is just a KeyBundle with a collection attached.
|
||||
*/
|
||||
function BulkKeyBundle(collection) {
|
||||
let log = Log4Moz.repository.getLogger("Sync.BulkKeyBundle");
|
||||
log.info("BulkKeyBundle being created for " + collection);
|
||||
KeyBundle.call(this);
|
||||
|
||||
this._collection = collection;
|
||||
}
|
||||
|
||||
BulkKeyBundle.prototype = {
|
||||
__proto__: KeyBundle.prototype,
|
||||
|
||||
get collection() {
|
||||
return this._collection;
|
||||
},
|
||||
|
||||
/**
|
||||
* Obtain the key pair in this key bundle.
|
||||
*
|
||||
* The returned keys are represented as raw byte strings.
|
||||
*/
|
||||
get keyPair() {
|
||||
return [this.encryptionKey, this.hmacKey];
|
||||
},
|
||||
|
||||
set keyPair(value) {
|
||||
if (!Array.isArray(value) || value.length != 2) {
|
||||
throw new Error("BulkKeyBundle.keyPair value must be array of 2 keys.");
|
||||
}
|
||||
|
||||
this.encryptionKey = value[0];
|
||||
this.hmacKey = value[1];
|
||||
},
|
||||
|
||||
get keyPairB64() {
|
||||
return [this.encryptionKeyB64, this.hmacKeyB64];
|
||||
},
|
||||
|
||||
set keyPairB64(value) {
|
||||
if (!Array.isArray(value) || value.length != 2) {
|
||||
throw new Error("BulkKeyBundle.keyPairB64 value must be an array of 2 " +
|
||||
"keys.");
|
||||
}
|
||||
|
||||
this.encryptionKey = Utils.safeAtoB(value[0]);
|
||||
this.hmacKey = Utils.safeAtoB(value[1]);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a key pair derived from a Sync Key via HKDF.
|
||||
*
|
||||
* Instances of this type should be considered immutable. You create an
|
||||
* instance by specifying the username and 26 character "friendly" Base32
|
||||
* encoded Sync Key. The Sync Key is derived at instance creation time.
|
||||
*
|
||||
* If the username or Sync Key is invalid, an Error will be thrown.
|
||||
*/
|
||||
function SyncKeyBundle(username, syncKey) {
|
||||
let log = Log4Moz.repository.getLogger("Sync.SyncKeyBundle");
|
||||
log.info("SyncKeyBundle being created.");
|
||||
KeyBundle.call(this);
|
||||
|
||||
this.generateFromKey(username, syncKey);
|
||||
}
|
||||
SyncKeyBundle.prototype = {
|
||||
__proto__: KeyBundle.prototype,
|
||||
|
||||
/*
|
||||
* If we've got a string, hash it into keys and store them.
|
||||
*/
|
||||
generateFromKey: function generateFromKey(username, syncKey) {
|
||||
if (!username || (typeof username != "string")) {
|
||||
throw new Error("Sync Key cannot be generated from non-string username.");
|
||||
}
|
||||
|
||||
if (!syncKey || (typeof syncKey != "string")) {
|
||||
throw new Error("Sync Key cannot be generated from non-string key.");
|
||||
}
|
||||
|
||||
if (!Utils.isPassphrase(syncKey)) {
|
||||
throw new Error("Provided key is not a passphrase, cannot derive Sync " +
|
||||
"Key Bundle.");
|
||||
}
|
||||
|
||||
// Expand the base32 Sync Key to an AES 256 and 256 bit HMAC key.
|
||||
let prk = Utils.decodeKeyBase32(syncKey);
|
||||
let info = HMAC_INPUT + username;
|
||||
let okm = Utils.hkdfExpand(prk, info, 32 * 2);
|
||||
this.encryptionKey = okm.slice(0, 32);
|
||||
this.hmacKey = okm.slice(32, 64);
|
||||
},
|
||||
};
|
||||
|
|
@ -40,7 +40,7 @@ const EXPORTED_SYMBOLS = ['Weave'];
|
|||
let Weave = {};
|
||||
Components.utils.import("resource://services-sync/constants.js", Weave);
|
||||
let lazies = {
|
||||
"record.js": ["CollectionKeys", "BulkKeyBundle", "SyncKeyBundle"],
|
||||
"record.js": ["CollectionKeys"],
|
||||
"engines.js": ['Engines', 'Engine', 'SyncEngine', 'Store'],
|
||||
"engines/addons.js": ["AddonsEngine"],
|
||||
"engines/bookmarks.js": ['BookmarksEngine', 'BookmarksSharingManager'],
|
||||
|
@ -51,13 +51,13 @@ let lazies = {
|
|||
"engines/passwords.js": ["PasswordEngine"],
|
||||
"engines/tabs.js": ["TabEngine"],
|
||||
"engines/apps.js": ["AppsEngine"],
|
||||
"identity.js": ["Identity", "ID"],
|
||||
"identity.js": ["Identity"],
|
||||
"jpakeclient.js": ["JPAKEClient"],
|
||||
"keys.js": ["BulkKeyBundle", "SyncKeyBundle"],
|
||||
"notifications.js": ["Notifications", "Notification", "NotificationButton"],
|
||||
"policies.js": ["SyncScheduler", "ErrorHandler",
|
||||
"SendCredentialsController"],
|
||||
"resource.js": ["Resource", "AsyncResource", "Auth",
|
||||
"BasicAuthenticator", "NoOpAuthenticator"],
|
||||
"resource.js": ["Resource", "AsyncResource"],
|
||||
"service.js": ["Service"],
|
||||
"status.js": ["Status"],
|
||||
"util.js": ['Utils', 'Svc', 'Str']
|
||||
|
|
|
@ -420,7 +420,9 @@ let SyncScheduler = {
|
|||
* non-syncing.
|
||||
*/
|
||||
scheduleAtInterval: function scheduleAtInterval(minimumInterval) {
|
||||
let interval = Utils.calculateBackoff(this._syncErrors, MINIMUM_BACKOFF_INTERVAL);
|
||||
let interval = Utils.calculateBackoff(this._syncErrors,
|
||||
MINIMUM_BACKOFF_INTERVAL,
|
||||
Status.backoffInterval);
|
||||
if (minimumInterval) {
|
||||
interval = Math.max(minimumInterval, interval);
|
||||
}
|
||||
|
@ -907,9 +909,9 @@ SendCredentialsController.prototype = {
|
|||
|
||||
sendCredentials: function sendCredentials() {
|
||||
this._log.trace("Sending credentials.");
|
||||
let credentials = {account: Weave.Service.account,
|
||||
password: Weave.Service.password,
|
||||
synckey: Weave.Service.passphrase,
|
||||
let credentials = {account: Weave.Identity.account,
|
||||
password: Weave.Identity.basicPassword,
|
||||
synckey: Weave.Identity.syncKey,
|
||||
serverURL: Weave.Service.serverURL};
|
||||
this.jpakeclient.sendAndComplete(credentials);
|
||||
},
|
||||
|
|
|
@ -38,8 +38,7 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const EXPORTED_SYMBOLS = ["WBORecord", "RecordManager", "Records",
|
||||
"CryptoWrapper", "CollectionKeys", "BulkKeyBundle",
|
||||
"SyncKeyBundle", "Collection"];
|
||||
"CryptoWrapper", "CollectionKeys", "Collection"];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
@ -51,6 +50,7 @@ const KEYS_WBO = "keys";
|
|||
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/keys.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
Cu.import("resource://services-sync/resource.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
@ -198,8 +198,9 @@ CryptoWrapper.prototype = {
|
|||
|
||||
ciphertextHMAC: function ciphertextHMAC(keyBundle) {
|
||||
let hasher = keyBundle.sha256HMACHasher;
|
||||
if (!hasher)
|
||||
if (!hasher) {
|
||||
throw "Cannot compute HMAC without an HMAC key.";
|
||||
}
|
||||
|
||||
return Utils.bytesAsHex(Utils.digestUTF8(this.ciphertext, hasher));
|
||||
},
|
||||
|
@ -215,12 +216,13 @@ CryptoWrapper.prototype = {
|
|||
*/
|
||||
encrypt: function encrypt(keyBundle) {
|
||||
keyBundle = keyBundle || CollectionKeys.keyForCollection(this.collection);
|
||||
if (!keyBundle)
|
||||
if (!keyBundle) {
|
||||
throw new Error("Key bundle is null for " + this.uri.spec);
|
||||
}
|
||||
|
||||
this.IV = Svc.Crypto.generateRandomIV();
|
||||
this.ciphertext = Svc.Crypto.encrypt(JSON.stringify(this.cleartext),
|
||||
keyBundle.encryptionKey, this.IV);
|
||||
keyBundle.encryptionKeyB64, this.IV);
|
||||
this.hmac = this.ciphertextHMAC(keyBundle);
|
||||
this.cleartext = null;
|
||||
},
|
||||
|
@ -232,8 +234,9 @@ CryptoWrapper.prototype = {
|
|||
}
|
||||
|
||||
keyBundle = keyBundle || CollectionKeys.keyForCollection(this.collection);
|
||||
if (!keyBundle)
|
||||
if (!keyBundle) {
|
||||
throw new Error("Key bundle is null for " + this.collection + "/" + this.id);
|
||||
}
|
||||
|
||||
// Authenticate the encrypted blob with the expected HMAC
|
||||
let computedHMAC = this.ciphertextHMAC(keyBundle);
|
||||
|
@ -244,7 +247,7 @@ CryptoWrapper.prototype = {
|
|||
|
||||
// Handle invalid data here. Elsewhere we assume that cleartext is an object.
|
||||
let cleartext = Svc.Crypto.decrypt(this.ciphertext,
|
||||
keyBundle.encryptionKey, this.IV);
|
||||
keyBundle.encryptionKeyB64, this.IV);
|
||||
let json_result = JSON.parse(cleartext);
|
||||
|
||||
if (json_result && (json_result instanceof Object)) {
|
||||
|
@ -293,8 +296,7 @@ XPCOMUtils.defineLazyGetter(this, "CollectionKeys", function () {
|
|||
|
||||
|
||||
/**
|
||||
* Keeps track of mappings between collection names ('tabs') and
|
||||
* keyStrs, which you can feed into KeyBundle to get encryption tokens.
|
||||
* Keeps track of mappings between collection names ('tabs') and KeyBundles.
|
||||
*
|
||||
* You can update this thing simply by giving it /info/collections. It'll
|
||||
* use the last modified time to bring itself up to date.
|
||||
|
@ -365,10 +367,10 @@ CollectionKeyManager.prototype = {
|
|||
let wbo = new CryptoWrapper(CRYPTO_COLLECTION, KEYS_WBO);
|
||||
let c = {};
|
||||
for (let k in collections) {
|
||||
c[k] = collections[k].keyPair;
|
||||
c[k] = collections[k].keyPairB64;
|
||||
}
|
||||
wbo.cleartext = {
|
||||
"default": defaultBundle ? defaultBundle.keyPair : null,
|
||||
"default": defaultBundle ? defaultBundle.keyPairB64 : null,
|
||||
"collections": c,
|
||||
"collection": CRYPTO_COLLECTION,
|
||||
"id": KEYS_WBO
|
||||
|
@ -386,13 +388,13 @@ CollectionKeyManager.prototype = {
|
|||
* Compute a new default key, and new keys for any specified collections.
|
||||
*/
|
||||
newKeys: function(collections) {
|
||||
let newDefaultKey = new BulkKeyBundle(null, DEFAULT_KEYBUNDLE_NAME);
|
||||
let newDefaultKey = new BulkKeyBundle(DEFAULT_KEYBUNDLE_NAME);
|
||||
newDefaultKey.generateRandom();
|
||||
|
||||
let newColls = {};
|
||||
if (collections) {
|
||||
collections.forEach(function (c) {
|
||||
let b = new BulkKeyBundle(null, c);
|
||||
let b = new BulkKeyBundle(c);
|
||||
b.generateRandom();
|
||||
newColls[c] = b;
|
||||
});
|
||||
|
@ -459,8 +461,8 @@ CollectionKeyManager.prototype = {
|
|||
}
|
||||
|
||||
// Process the incoming default key.
|
||||
let b = new BulkKeyBundle(null, DEFAULT_KEYBUNDLE_NAME);
|
||||
b.keyPair = payload.default;
|
||||
let b = new BulkKeyBundle(DEFAULT_KEYBUNDLE_NAME);
|
||||
b.keyPairB64 = payload.default;
|
||||
let newDefault = b;
|
||||
|
||||
// Process the incoming collections.
|
||||
|
@ -471,8 +473,8 @@ CollectionKeyManager.prototype = {
|
|||
for (let k in colls) {
|
||||
let v = colls[k];
|
||||
if (v) {
|
||||
let keyObj = new BulkKeyBundle(null, k);
|
||||
keyObj.keyPair = v;
|
||||
let keyObj = new BulkKeyBundle(k);
|
||||
keyObj.keyPairB64 = v;
|
||||
if (keyObj) {
|
||||
newCollections[k] = keyObj;
|
||||
}
|
||||
|
@ -528,202 +530,6 @@ CollectionKeyManager.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Abuse Identity: store the collection name (or default) in the
|
||||
* username field, and the keyStr in the password field.
|
||||
*
|
||||
* We very rarely want to override the realm, so pass null and
|
||||
* it'll default to PWDMGR_KEYBUNDLE_REALM.
|
||||
*
|
||||
* KeyBundle is the base class for two similar classes:
|
||||
*
|
||||
* SyncKeyBundle:
|
||||
*
|
||||
* A key string is provided, and it must be hashed to derive two different
|
||||
* keys (one HMAC, one AES).
|
||||
*
|
||||
* BulkKeyBundle:
|
||||
*
|
||||
* Two independent keys are provided, or randomly generated on request.
|
||||
*
|
||||
*/
|
||||
function KeyBundle(realm, collectionName, keyStr) {
|
||||
let realm = realm || PWDMGR_KEYBUNDLE_REALM;
|
||||
|
||||
if (keyStr && !keyStr.charAt)
|
||||
// Ensure it's valid.
|
||||
throw "KeyBundle given non-string key.";
|
||||
|
||||
Identity.call(this, realm, collectionName, keyStr);
|
||||
}
|
||||
KeyBundle.prototype = {
|
||||
__proto__: Identity.prototype,
|
||||
|
||||
_encrypt: null,
|
||||
_hmac: null,
|
||||
_hmacObj: null,
|
||||
_sha256HMACHasher: null,
|
||||
|
||||
equals: function equals(bundle) {
|
||||
return bundle &&
|
||||
(bundle.hmacKey == this.hmacKey) &&
|
||||
(bundle.encryptionKey == this.encryptionKey);
|
||||
},
|
||||
|
||||
/*
|
||||
* Accessors for the two keys.
|
||||
*/
|
||||
get encryptionKey() {
|
||||
return this._encrypt;
|
||||
},
|
||||
|
||||
set encryptionKey(value) {
|
||||
this._encrypt = value;
|
||||
},
|
||||
|
||||
get hmacKey() {
|
||||
return this._hmac;
|
||||
},
|
||||
|
||||
set hmacKey(value) {
|
||||
this._hmac = value;
|
||||
this._hmacObj = value ? Utils.makeHMACKey(value) : null;
|
||||
this._sha256HMACHasher = value ? Utils.makeHMACHasher(
|
||||
Ci.nsICryptoHMAC.SHA256, this._hmacObj) : null;
|
||||
},
|
||||
|
||||
get hmacKeyObject() {
|
||||
return this._hmacObj;
|
||||
},
|
||||
|
||||
get sha256HMACHasher() {
|
||||
return this._sha256HMACHasher;
|
||||
}
|
||||
};
|
||||
|
||||
function BulkKeyBundle(realm, collectionName) {
|
||||
let log = Log4Moz.repository.getLogger("Sync.BulkKeyBundle");
|
||||
log.info("BulkKeyBundle being created for " + collectionName);
|
||||
KeyBundle.call(this, realm, collectionName);
|
||||
}
|
||||
|
||||
BulkKeyBundle.prototype = {
|
||||
__proto__: KeyBundle.prototype,
|
||||
|
||||
generateRandom: function generateRandom() {
|
||||
let generatedHMAC = Svc.Crypto.generateRandomKey();
|
||||
let generatedEncr = Svc.Crypto.generateRandomKey();
|
||||
this.keyPair = [generatedEncr, generatedHMAC];
|
||||
},
|
||||
|
||||
get keyPair() {
|
||||
return [this._encrypt, btoa(this._hmac)];
|
||||
},
|
||||
|
||||
/*
|
||||
* Use keyPair = [enc, hmac], or generateRandom(), when
|
||||
* you want to manage the two individual keys.
|
||||
*/
|
||||
set keyPair(value) {
|
||||
if (value.length && (value.length == 2)) {
|
||||
let json = JSON.stringify(value);
|
||||
let en = value[0];
|
||||
let hm = value[1];
|
||||
|
||||
this.password = json;
|
||||
this.hmacKey = Utils.safeAtoB(hm);
|
||||
this._encrypt = en; // Store in base64.
|
||||
}
|
||||
else {
|
||||
throw "Invalid keypair";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function SyncKeyBundle(realm, collectionName, syncKey) {
|
||||
let log = Log4Moz.repository.getLogger("Sync.SyncKeyBundle");
|
||||
log.info("SyncKeyBundle being created for " + collectionName);
|
||||
KeyBundle.call(this, realm, collectionName, syncKey);
|
||||
if (syncKey)
|
||||
this.keyStr = syncKey; // Accessor sets up keys.
|
||||
}
|
||||
|
||||
SyncKeyBundle.prototype = {
|
||||
__proto__: KeyBundle.prototype,
|
||||
|
||||
/*
|
||||
* Use keyStr when you want to work with a key string that's
|
||||
* hashed into individual keys.
|
||||
*/
|
||||
get keyStr() {
|
||||
return this.password;
|
||||
},
|
||||
|
||||
set keyStr(value) {
|
||||
this.password = value;
|
||||
this._hmac = null;
|
||||
this._hmacObj = null;
|
||||
this._encrypt = null;
|
||||
this._sha256HMACHasher = null;
|
||||
},
|
||||
|
||||
/*
|
||||
* Can't rely on password being set through any of our setters:
|
||||
* Identity does work under the hood.
|
||||
*
|
||||
* Consequently, make sure we derive keys if that work hasn't already been
|
||||
* done.
|
||||
*/
|
||||
get encryptionKey() {
|
||||
if (!this._encrypt)
|
||||
this.generateEntry();
|
||||
return this._encrypt;
|
||||
},
|
||||
|
||||
get hmacKey() {
|
||||
if (!this._hmac)
|
||||
this.generateEntry();
|
||||
return this._hmac;
|
||||
},
|
||||
|
||||
get hmacKeyObject() {
|
||||
if (!this._hmacObj)
|
||||
this.generateEntry();
|
||||
return this._hmacObj;
|
||||
},
|
||||
|
||||
get sha256HMACHasher() {
|
||||
if (!this._sha256HMACHasher)
|
||||
this.generateEntry();
|
||||
return this._sha256HMACHasher;
|
||||
},
|
||||
|
||||
/*
|
||||
* If we've got a string, hash it into keys and store them.
|
||||
*/
|
||||
generateEntry: function generateEntry() {
|
||||
let syncKey = this.keyStr;
|
||||
if (!syncKey)
|
||||
return;
|
||||
|
||||
// Expand the base32 Sync Key to an AES 256 and 256 bit HMAC key.
|
||||
let prk = Utils.decodeKeyBase32(syncKey);
|
||||
let info = HMAC_INPUT + this.username;
|
||||
let okm = Utils.hkdfExpand(prk, info, 32 * 2);
|
||||
let enc = okm.slice(0, 32);
|
||||
let hmac = okm.slice(32, 64);
|
||||
|
||||
// Save them.
|
||||
this._encrypt = btoa(enc);
|
||||
// Individual sets: cheaper than calling parent setter.
|
||||
this._hmac = hmac;
|
||||
this._hmacObj = Utils.makeHMACKey(hmac);
|
||||
this._sha256HMACHasher = Utils.makeHMACHasher(
|
||||
Ci.nsICryptoHMAC.SHA256, this._hmacObj);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function Collection(uri, recordObj) {
|
||||
Resource.call(this, uri);
|
||||
this._recordObj = recordObj;
|
||||
|
|
|
@ -37,9 +37,10 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const EXPORTED_SYMBOLS = ["Resource", "AsyncResource",
|
||||
"Auth", "BrokenBasicAuthenticator",
|
||||
"BasicAuthenticator", "NoOpAuthenticator"];
|
||||
const EXPORTED_SYMBOLS = [
|
||||
"AsyncResource",
|
||||
"Resource"
|
||||
];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
@ -50,68 +51,10 @@ Cu.import("resource://services-sync/async.js");
|
|||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/ext/Observers.js");
|
||||
Cu.import("resource://services-sync/ext/Preferences.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "Auth", function () {
|
||||
return new AuthMgr();
|
||||
});
|
||||
|
||||
// XXX: the authenticator api will probably need to be changed to support
|
||||
// other methods (digest, oauth, etc)
|
||||
|
||||
function NoOpAuthenticator() {}
|
||||
NoOpAuthenticator.prototype = {
|
||||
onRequest: function NoOpAuth_onRequest(headers) {
|
||||
return headers;
|
||||
}
|
||||
};
|
||||
|
||||
// Warning: This will drop the high unicode bytes from passwords.
|
||||
// Use BasicAuthenticator to send non-ASCII passwords UTF8-encoded.
|
||||
function BrokenBasicAuthenticator(identity) {
|
||||
this._id = identity;
|
||||
}
|
||||
BrokenBasicAuthenticator.prototype = {
|
||||
onRequest: function BasicAuth_onRequest(headers) {
|
||||
headers['authorization'] = 'Basic ' +
|
||||
btoa(this._id.username + ':' + this._id.password);
|
||||
return headers;
|
||||
}
|
||||
};
|
||||
|
||||
function BasicAuthenticator(identity) {
|
||||
this._id = identity;
|
||||
}
|
||||
BasicAuthenticator.prototype = {
|
||||
onRequest: function onRequest(headers) {
|
||||
headers['authorization'] = 'Basic ' +
|
||||
btoa(this._id.username + ':' + this._id.passwordUTF8);
|
||||
return headers;
|
||||
}
|
||||
};
|
||||
|
||||
function AuthMgr() {
|
||||
this._authenticators = {};
|
||||
this.defaultAuthenticator = new NoOpAuthenticator();
|
||||
}
|
||||
AuthMgr.prototype = {
|
||||
defaultAuthenticator: null,
|
||||
|
||||
registerAuthenticator: function AuthMgr_register(match, authenticator) {
|
||||
this._authenticators[match] = authenticator;
|
||||
},
|
||||
|
||||
lookupAuthenticator: function AuthMgr_lookup(uri) {
|
||||
for (let match in this._authenticators) {
|
||||
if (uri.match(match))
|
||||
return this._authenticators[match];
|
||||
}
|
||||
return this.defaultAuthenticator;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* AsyncResource represents a remote network resource, identified by a URI.
|
||||
* Create an instance like so:
|
||||
|
@ -150,6 +93,14 @@ AsyncResource.prototype = {
|
|||
// Caches the latest server timestamp (X-Weave-Timestamp header).
|
||||
serverTime: null,
|
||||
|
||||
/**
|
||||
* Callback to be invoked at request time to add authentication details.
|
||||
*
|
||||
* By default, a global authenticator is provided. If this is set, it will
|
||||
* be used instead of the global one.
|
||||
*/
|
||||
authenticator: null,
|
||||
|
||||
// The string to use as the base User-Agent in Sync requests.
|
||||
// These strings will look something like
|
||||
//
|
||||
|
@ -167,29 +118,13 @@ AsyncResource.prototype = {
|
|||
// Wait 5 minutes before killing a request.
|
||||
ABORT_TIMEOUT: 300000,
|
||||
|
||||
// ** {{{ AsyncResource.authenticator }}} **
|
||||
//
|
||||
// Getter and setter for the authenticator module
|
||||
// responsible for this particular resource. The authenticator
|
||||
// module may modify the headers to perform authentication
|
||||
// while performing a request for the resource, for example.
|
||||
get authenticator() {
|
||||
if (this._authenticator)
|
||||
return this._authenticator;
|
||||
else
|
||||
return Auth.lookupAuthenticator(this.spec);
|
||||
},
|
||||
set authenticator(value) {
|
||||
this._authenticator = value;
|
||||
},
|
||||
|
||||
// ** {{{ AsyncResource.headers }}} **
|
||||
//
|
||||
// Headers to be included when making a request for the resource.
|
||||
// Note: Header names should be all lower case, there's no explicit
|
||||
// check for duplicates due to case!
|
||||
get headers() {
|
||||
return this.authenticator.onRequest(this._headers);
|
||||
return this._headers;
|
||||
},
|
||||
set headers(value) {
|
||||
this._headers = value;
|
||||
|
@ -235,7 +170,7 @@ AsyncResource.prototype = {
|
|||
// through. It is never called directly, only {{{_doRequest}}} uses it
|
||||
// to obtain a request channel.
|
||||
//
|
||||
_createRequest: function Res__createRequest() {
|
||||
_createRequest: function Res__createRequest(method) {
|
||||
let channel = Services.io.newChannel(this.spec, null, null)
|
||||
.QueryInterface(Ci.nsIRequest)
|
||||
.QueryInterface(Ci.nsIHttpChannel);
|
||||
|
@ -253,9 +188,24 @@ AsyncResource.prototype = {
|
|||
channel.setRequestHeader("user-agent", ua, false);
|
||||
}
|
||||
|
||||
// Avoid calling the authorizer more than once.
|
||||
let headers = this.headers;
|
||||
for (let key in headers) {
|
||||
|
||||
let authenticator = this.authenticator;
|
||||
if (!authenticator) {
|
||||
authenticator = Identity.getResourceAuthenticator();
|
||||
}
|
||||
if (authenticator) {
|
||||
let result = authenticator(this, method);
|
||||
if (result && result.headers) {
|
||||
for (let [k, v] in Iterator(result.headers)) {
|
||||
headers[k.toLowerCase()] = v;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this._log.debug("No authenticator found.");
|
||||
}
|
||||
|
||||
for (let [key, value] in Iterator(headers)) {
|
||||
if (key == 'authorization')
|
||||
this._log.trace("HTTP Header " + key + ": ***** (suppressed)");
|
||||
else
|
||||
|
@ -270,7 +220,7 @@ AsyncResource.prototype = {
|
|||
_doRequest: function _doRequest(action, data, callback) {
|
||||
this._log.trace("In _doRequest.");
|
||||
this._callback = callback;
|
||||
let channel = this._createRequest();
|
||||
let channel = this._createRequest(action);
|
||||
|
||||
if ("undefined" != typeof(data))
|
||||
this._data = data;
|
||||
|
|
|
@ -654,13 +654,11 @@ SyncStorageRequest.prototype = {
|
|||
this.setHeader("user-agent", ua);
|
||||
}
|
||||
|
||||
// Set the BasicAuth header.
|
||||
let id = ID.get("WeaveID");
|
||||
if (id) {
|
||||
let auth_header = "Basic " + btoa(id.username + ':' + id.passwordUTF8);
|
||||
this.setHeader("authorization", auth_header);
|
||||
let authenticator = Identity.getRESTRequestAuthenticator();
|
||||
if (authenticator) {
|
||||
authenticator(this);
|
||||
} else {
|
||||
this._log.debug("Couldn't set Authentication header: WeaveID not found.");
|
||||
this._log.debug("No authenticator found.");
|
||||
}
|
||||
|
||||
return RESTRequest.prototype.dispatch.apply(this, arguments);
|
||||
|
|
|
@ -91,53 +91,13 @@ WeaveSvc.prototype = {
|
|||
_lock: Utils.lock,
|
||||
_locked: false,
|
||||
_loggedIn: false,
|
||||
_identity: Weave.Identity,
|
||||
|
||||
get account() Svc.Prefs.get("account", this.username),
|
||||
set account(value) {
|
||||
if (value) {
|
||||
value = value.toLowerCase();
|
||||
Svc.Prefs.set("account", value);
|
||||
} else {
|
||||
Svc.Prefs.reset("account");
|
||||
}
|
||||
this.username = this._usernameFromAccount(value);
|
||||
},
|
||||
|
||||
_usernameFromAccount: function _usernameFromAccount(value) {
|
||||
// If we encounter characters not allowed by the API (as found for
|
||||
// instance in an email address), hash the value.
|
||||
if (value && value.match(/[^A-Z0-9._-]/i))
|
||||
return Utils.sha1Base32(value.toLowerCase()).toLowerCase();
|
||||
return value;
|
||||
},
|
||||
|
||||
get username() {
|
||||
return Svc.Prefs.get("username", "").toLowerCase();
|
||||
},
|
||||
set username(value) {
|
||||
if (value) {
|
||||
// Make sure all uses of this new username is lowercase
|
||||
value = value.toLowerCase();
|
||||
Svc.Prefs.set("username", value);
|
||||
}
|
||||
else
|
||||
Svc.Prefs.reset("username");
|
||||
|
||||
// fixme - need to loop over all Identity objects - needs some rethinking...
|
||||
ID.get('WeaveID').username = value;
|
||||
ID.get('WeaveCryptoID').username = value;
|
||||
|
||||
// FIXME: need to also call this whenever the username pref changes
|
||||
this._updateCachedURLs();
|
||||
},
|
||||
|
||||
get password() ID.get("WeaveID").password,
|
||||
set password(value) ID.get("WeaveID").password = value,
|
||||
|
||||
get passphrase() ID.get("WeaveCryptoID").keyStr,
|
||||
set passphrase(value) ID.get("WeaveCryptoID").keyStr = value,
|
||||
|
||||
get syncKeyBundle() ID.get("WeaveCryptoID"),
|
||||
userBaseURL: null,
|
||||
infoURL: null,
|
||||
storageURL: null,
|
||||
metaURL: null,
|
||||
cryptoKeyURL: null,
|
||||
|
||||
get serverURL() Svc.Prefs.get("serverURL"),
|
||||
set serverURL(value) {
|
||||
|
@ -218,11 +178,11 @@ WeaveSvc.prototype = {
|
|||
|
||||
_updateCachedURLs: function _updateCachedURLs() {
|
||||
// Nothing to cache yet if we don't have the building blocks
|
||||
if (this.clusterURL == "" || this.username == "")
|
||||
if (this.clusterURL == "" || this._identity.username == "")
|
||||
return;
|
||||
|
||||
let storageAPI = this.clusterURL + SYNC_API_VERSION + "/";
|
||||
this.userBaseURL = storageAPI + this.username + "/";
|
||||
this.userBaseURL = storageAPI + this._identity.username + "/";
|
||||
this._log.debug("Caching URLs under storage user base: " + this.userBaseURL);
|
||||
|
||||
// Generate and cache various URLs under the storage API for this user
|
||||
|
@ -301,7 +261,7 @@ WeaveSvc.prototype = {
|
|||
return false;
|
||||
}
|
||||
|
||||
let keysChanged = this.handleFetchedKeys(this.syncKeyBundle,
|
||||
let keysChanged = this.handleFetchedKeys(this._identity.syncKeyBundle,
|
||||
cryptoKeys, true);
|
||||
if (keysChanged) {
|
||||
// Did they change? If so, carry on.
|
||||
|
@ -390,24 +350,16 @@ WeaveSvc.prototype = {
|
|||
|
||||
SyncScheduler.init();
|
||||
|
||||
if (!this.enabled)
|
||||
this._log.info("Weave Sync disabled");
|
||||
|
||||
// Create Weave identities (for logging in, and for encryption)
|
||||
let id = ID.get("WeaveID");
|
||||
if (!id)
|
||||
id = ID.set("WeaveID", new Identity(PWDMGR_PASSWORD_REALM, this.username));
|
||||
Auth.defaultAuthenticator = new BasicAuthenticator(id);
|
||||
|
||||
if (!ID.get("WeaveCryptoID"))
|
||||
ID.set("WeaveCryptoID",
|
||||
new SyncKeyBundle(PWDMGR_PASSPHRASE_REALM, this.username));
|
||||
if (!this.enabled) {
|
||||
this._log.info("Firefox Sync disabled.");
|
||||
}
|
||||
|
||||
this._updateCachedURLs();
|
||||
|
||||
let status = this._checkSetup();
|
||||
if (status != STATUS_DISABLED && status != CLIENT_NOT_CONFIGURED)
|
||||
if (status != STATUS_DISABLED && status != CLIENT_NOT_CONFIGURED) {
|
||||
Svc.Obs.notify("weave:engine:start-tracking");
|
||||
}
|
||||
|
||||
// Send an event now that Weave service is ready. We don't do this
|
||||
// synchronously so that observers can import this module before
|
||||
|
@ -418,9 +370,10 @@ WeaveSvc.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
_checkSetup: function WeaveSvc__checkSetup() {
|
||||
if (!this.enabled)
|
||||
_checkSetup: function _checkSetup() {
|
||||
if (!this.enabled) {
|
||||
return Status.service = STATUS_DISABLED;
|
||||
}
|
||||
return Status.checkSetup();
|
||||
},
|
||||
|
||||
|
@ -507,10 +460,10 @@ WeaveSvc.prototype = {
|
|||
|
||||
// gets cluster from central LDAP server and returns it, or null on error
|
||||
_findCluster: function _findCluster() {
|
||||
this._log.debug("Finding cluster for user " + this.username);
|
||||
this._log.debug("Finding cluster for user " + this._identity.username);
|
||||
|
||||
let fail;
|
||||
let res = new Resource(this.userAPI + this.username + "/node/weave");
|
||||
let res = new Resource(this.userAPI + this._identity.username + "/node/weave");
|
||||
try {
|
||||
let node = res.get();
|
||||
switch (node.status) {
|
||||
|
@ -601,8 +554,8 @@ WeaveSvc.prototype = {
|
|||
// Furthermore, we assume that our sync key is already upgraded,
|
||||
// and fail if that assumption is invalidated.
|
||||
|
||||
let syncKey = this.syncKeyBundle;
|
||||
if (!syncKey) {
|
||||
let syncKeyBundle = this._identity.syncKeyBundle;
|
||||
if (!syncKeyBundle) {
|
||||
this._log.error("No sync key: cannot fetch symmetric keys.");
|
||||
Status.login = LOGIN_FAILED_NO_PASSPHRASE;
|
||||
Status.sync = CREDENTIALS_CHANGED; // For want of a better option.
|
||||
|
@ -610,7 +563,7 @@ WeaveSvc.prototype = {
|
|||
}
|
||||
|
||||
// Not sure this validation is necessary now.
|
||||
if (!Utils.isPassphrase(syncKey.keyStr)) {
|
||||
if (!Utils.isPassphrase(this._identity.syncKey)) {
|
||||
this._log.warn("Sync key input is invalid: cannot fetch symmetric keys.");
|
||||
Status.login = LOGIN_FAILED_INVALID_PASSPHRASE;
|
||||
Status.sync = CREDENTIALS_CHANGED;
|
||||
|
@ -647,7 +600,7 @@ WeaveSvc.prototype = {
|
|||
let cryptoResp = cryptoKeys.fetch(this.cryptoKeysURL).response;
|
||||
|
||||
if (cryptoResp.success) {
|
||||
let keysChanged = this.handleFetchedKeys(syncKey, cryptoKeys);
|
||||
let keysChanged = this.handleFetchedKeys(syncKeyBundle, cryptoKeys);
|
||||
return true;
|
||||
}
|
||||
else if (cryptoResp.status == 404) {
|
||||
|
@ -715,7 +668,7 @@ WeaveSvc.prototype = {
|
|||
|
||||
verifyLogin: function verifyLogin()
|
||||
this._notify("verify-login", "", function() {
|
||||
if (!this.username) {
|
||||
if (!this._identity.username) {
|
||||
this._log.warn("No username in verifyLogin.");
|
||||
Status.login = LOGIN_FAILED_NO_USERNAME;
|
||||
return false;
|
||||
|
@ -727,7 +680,7 @@ WeaveSvc.prototype = {
|
|||
// exceptions!
|
||||
// Try to fetch the passphrase first, while we still have control.
|
||||
try {
|
||||
this.passphrase;
|
||||
this._identity.syncKey;
|
||||
} catch (ex) {
|
||||
this._log.debug("Fetching passphrase threw " + ex +
|
||||
"; assuming master password locked.");
|
||||
|
@ -755,7 +708,7 @@ WeaveSvc.prototype = {
|
|||
// We have no way of verifying the passphrase right now,
|
||||
// so wait until remoteSetup to do so.
|
||||
// Just make the most trivial checks.
|
||||
if (!this.passphrase) {
|
||||
if (!this._identity.syncKey) {
|
||||
this._log.warn("No passphrase in verifyLogin.");
|
||||
Status.login = LOGIN_FAILED_NO_PASSPHRASE;
|
||||
return false;
|
||||
|
@ -775,26 +728,8 @@ WeaveSvc.prototype = {
|
|||
|
||||
case 401:
|
||||
this._log.warn("401: login failed.");
|
||||
// Login failed. If the password contains non-ASCII characters,
|
||||
// perhaps the server password is an old low-byte only one?
|
||||
let id = ID.get('WeaveID');
|
||||
if (id.password != id.passwordUTF8) {
|
||||
let res = new Resource(this.infoURL);
|
||||
let auth = new BrokenBasicAuthenticator(id);
|
||||
res.authenticator = auth;
|
||||
test = res.get();
|
||||
if (test.status == 200) {
|
||||
this._log.debug("Non-ASCII password detected. "
|
||||
+ "Changing to UTF-8 version.");
|
||||
// Let's change the password on the server to the UTF8 version.
|
||||
let url = this.userAPI + this.username + "/password";
|
||||
res = new Resource(url);
|
||||
res.authenticator = auth;
|
||||
res.post(id.passwordUTF8);
|
||||
return this.verifyLogin();
|
||||
}
|
||||
}
|
||||
// Yes, we want to fall through to the 404 case.
|
||||
// Fall through to the 404 case.
|
||||
|
||||
case 404:
|
||||
// Check that we're verifying with the correct cluster
|
||||
if (this._setCluster())
|
||||
|
@ -825,7 +760,7 @@ WeaveSvc.prototype = {
|
|||
this._log.info("Generating new keys WBO...");
|
||||
let wbo = CollectionKeys.generateNewKeysWBO();
|
||||
this._log.info("Encrypting new key bundle.");
|
||||
wbo.encrypt(this.syncKeyBundle);
|
||||
wbo.encrypt(this._identity.syncKeyBundle);
|
||||
|
||||
this._log.info("Uploading...");
|
||||
let uploadRes = wbo.upload(this.cryptoKeysURL);
|
||||
|
@ -871,7 +806,7 @@ WeaveSvc.prototype = {
|
|||
this._log.warn("Failed to download keys.");
|
||||
throw new Error("Symmetric key download failed.");
|
||||
}
|
||||
let keysChanged = this.handleFetchedKeys(this.syncKeyBundle,
|
||||
let keysChanged = this.handleFetchedKeys(this._identity.syncKeyBundle,
|
||||
cryptoKeys, true);
|
||||
if (keysChanged) {
|
||||
this._log.info("Downloaded keys differed, as expected.");
|
||||
|
@ -880,7 +815,7 @@ WeaveSvc.prototype = {
|
|||
|
||||
changePassword: function WeaveSvc_changePassword(newpass)
|
||||
this._notify("changepwd", "", function() {
|
||||
let url = this.userAPI + this.username + "/password";
|
||||
let url = this.userAPI + this._identity.username + "/password";
|
||||
try {
|
||||
let resp = new Resource(url).post(Utils.encodeUTF8(newpass));
|
||||
if (resp.status != 200) {
|
||||
|
@ -895,7 +830,7 @@ WeaveSvc.prototype = {
|
|||
}
|
||||
|
||||
// Save the new password for requests and login manager.
|
||||
this.password = newpass;
|
||||
this._identity.basicPassword = newpass;
|
||||
this.persistLogin();
|
||||
return true;
|
||||
})(),
|
||||
|
@ -908,7 +843,7 @@ WeaveSvc.prototype = {
|
|||
this.logout();
|
||||
|
||||
/* Set this so UI is updated on next run. */
|
||||
this.passphrase = newphrase;
|
||||
this._identity.syncKey = newphrase;
|
||||
this.persistLogin();
|
||||
|
||||
/* We need to re-encrypt everything, so reset. */
|
||||
|
@ -920,7 +855,7 @@ WeaveSvc.prototype = {
|
|||
return true;
|
||||
}))(),
|
||||
|
||||
startOver: function() {
|
||||
startOver: function startOver() {
|
||||
this._log.trace("Invoking Service.startOver.");
|
||||
Svc.Obs.notify("weave:engine:stop-tracking");
|
||||
Status.resetSync();
|
||||
|
@ -928,7 +863,7 @@ WeaveSvc.prototype = {
|
|||
// We want let UI consumers of the following notification know as soon as
|
||||
// possible, so let's fake for the CLIENT_NOT_CONFIGURED status for now
|
||||
// by emptying the passphrase (we still need the password).
|
||||
Service.passphrase = "";
|
||||
this._identity.syncKey = null;
|
||||
Status.login = LOGIN_FAILED_NO_PASSPHRASE;
|
||||
this.logout();
|
||||
Svc.Obs.notify("weave:service:start-over");
|
||||
|
@ -959,23 +894,19 @@ WeaveSvc.prototype = {
|
|||
this._ignorePrefObserver = false;
|
||||
|
||||
Svc.Prefs.set("lastversion", WEAVE_VERSION);
|
||||
// Find weave logins and remove them.
|
||||
this.password = "";
|
||||
Services.logins.findLogins({}, PWDMGR_HOST, "", "").map(function(login) {
|
||||
Services.logins.removeLogin(login);
|
||||
});
|
||||
|
||||
this._identity.deleteSyncCredentials();
|
||||
},
|
||||
|
||||
persistLogin: function persistLogin() {
|
||||
// Canceled master password prompt can prevent these from succeeding.
|
||||
try {
|
||||
ID.get("WeaveID").persist();
|
||||
ID.get("WeaveCryptoID").persist();
|
||||
this._identity.persistCredentials();
|
||||
} catch (ex) {
|
||||
this._log.info("Unable to persist credentials: " + ex);
|
||||
}
|
||||
catch(ex) {}
|
||||
},
|
||||
|
||||
login: function WeaveSvc_login(username, password, passphrase)
|
||||
login: function login(username, password, passphrase)
|
||||
this._catch(this._lock("service.js: login",
|
||||
this._notify("login", "", function() {
|
||||
this._loggedIn = false;
|
||||
|
@ -985,23 +916,29 @@ WeaveSvc.prototype = {
|
|||
}
|
||||
|
||||
let initialStatus = this._checkSetup();
|
||||
if (username)
|
||||
this.username = username;
|
||||
if (password)
|
||||
this.password = password;
|
||||
if (passphrase)
|
||||
this.passphrase = passphrase;
|
||||
if (username) {
|
||||
this._identity.username = username;
|
||||
}
|
||||
if (password) {
|
||||
this._identity.basicPassword = password;
|
||||
}
|
||||
if (passphrase) {
|
||||
this._identity.syncKey = passphrase;
|
||||
}
|
||||
|
||||
if (this._checkSetup() == CLIENT_NOT_CONFIGURED)
|
||||
throw "aborting login, client not configured";
|
||||
if (this._checkSetup() == CLIENT_NOT_CONFIGURED) {
|
||||
throw "Aborting login, client not configured.";
|
||||
}
|
||||
|
||||
// Calling login() with parameters when the client was
|
||||
// previously not configured means setup was completed.
|
||||
if (initialStatus == CLIENT_NOT_CONFIGURED
|
||||
&& (username || password || passphrase))
|
||||
&& (username || password || passphrase)) {
|
||||
Svc.Obs.notify("weave:service:setup-complete");
|
||||
}
|
||||
|
||||
this._log.info("Logging in user " + this.username);
|
||||
this._log.info("Logging in user " + this._identity.username);
|
||||
this._updateCachedURLs();
|
||||
|
||||
if (!this.verifyLogin()) {
|
||||
// verifyLogin sets the failure states here.
|
||||
|
@ -1013,7 +950,7 @@ WeaveSvc.prototype = {
|
|||
return true;
|
||||
})))(),
|
||||
|
||||
logout: function WeaveSvc_logout() {
|
||||
logout: function logout() {
|
||||
// No need to do anything if we're already logged out.
|
||||
if (!this._loggedIn)
|
||||
return;
|
||||
|
@ -1025,10 +962,9 @@ WeaveSvc.prototype = {
|
|||
},
|
||||
|
||||
checkAccount: function checkAccount(account) {
|
||||
let username = this._usernameFromAccount(account);
|
||||
let username = this._identity.usernameFromAccount(account);
|
||||
let url = this.userAPI + username;
|
||||
let res = new Resource(url);
|
||||
res.authenticator = new NoOpAuthenticator();
|
||||
|
||||
let data = "";
|
||||
try {
|
||||
|
@ -1049,7 +985,7 @@ WeaveSvc.prototype = {
|
|||
|
||||
createAccount: function createAccount(email, password,
|
||||
captchaChallenge, captchaResponse) {
|
||||
let username = this._usernameFromAccount(email);
|
||||
let username = this._identity.usernameFromAccount(email);
|
||||
let payload = JSON.stringify({
|
||||
"password": Utils.encodeUTF8(password),
|
||||
"email": email,
|
||||
|
@ -1059,7 +995,6 @@ WeaveSvc.prototype = {
|
|||
|
||||
let url = this.userAPI + username;
|
||||
let res = new Resource(url);
|
||||
res.authenticator = new NoOpAuthenticator();
|
||||
|
||||
// Hint to server to allow scripted user creation or otherwise
|
||||
// ignore captcha.
|
||||
|
@ -1106,7 +1041,7 @@ WeaveSvc.prototype = {
|
|||
Records.del(this.metaURL);
|
||||
|
||||
// ... fetch the current record from the server, and COPY THE FLAGS.
|
||||
let newMeta = Records.get(this.metaURL);
|
||||
let newMeta = Records.get(this.metaURL);
|
||||
|
||||
if (!Records.response.success || !newMeta) {
|
||||
this._log.debug("No meta/global record on the server. Creating one.");
|
||||
|
@ -1508,21 +1443,6 @@ WeaveSvc.prototype = {
|
|||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Silently fixes case issues.
|
||||
*/
|
||||
syncKeyNeedsUpgrade: function syncKeyNeedsUpgrade() {
|
||||
let p = this.passphrase;
|
||||
|
||||
// Check whether it's already a key that we generated.
|
||||
if (Utils.isPassphrase(p)) {
|
||||
this._log.info("Sync key is up-to-date: no need to upgrade.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* If we have a passphrase, rather than a 25-alphadigit sync key,
|
||||
* use the provided sync ID to bootstrap it using PBKDF2.
|
||||
|
@ -1534,11 +1454,17 @@ WeaveSvc.prototype = {
|
|||
* we decide to bump the server storage version.
|
||||
*/
|
||||
upgradeSyncKey: function upgradeSyncKey(syncID) {
|
||||
let p = this.passphrase;
|
||||
let p = this._identity.syncKey;
|
||||
|
||||
if (!p) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check whether it's already a key that we generated.
|
||||
if (!this.syncKeyNeedsUpgrade(p))
|
||||
if (Utils.isPassphrase(p)) {
|
||||
this._log.info("Sync key is up-to-date: no need to upgrade.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, let's upgrade it.
|
||||
// N.B., we persist the sync key without testing it first...
|
||||
|
@ -1552,7 +1478,7 @@ WeaveSvc.prototype = {
|
|||
}
|
||||
|
||||
this._log.info("Upgrading sync key...");
|
||||
this.passphrase = k;
|
||||
this._identity.syncKey = k;
|
||||
this._log.info("Saving upgraded sync key...");
|
||||
this.persistLogin();
|
||||
this._log.info("Done saving.");
|
||||
|
|
|
@ -42,10 +42,12 @@ const Cu = Components.utils;
|
|||
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let Status = {
|
||||
_log: Log4Moz.repository.getLogger("Sync.Status"),
|
||||
_authManager: Identity,
|
||||
ready: false,
|
||||
|
||||
get service() {
|
||||
|
@ -109,46 +111,14 @@ let Status = {
|
|||
},
|
||||
|
||||
checkSetup: function checkSetup() {
|
||||
// Check whether we have a username without importing The World(tm).
|
||||
let prefs = Cc["@mozilla.org/preferences-service;1"]
|
||||
.getService(Ci.nsIPrefService)
|
||||
.getBranch(PREFS_BRANCH);
|
||||
let username;
|
||||
try {
|
||||
username = prefs.getCharPref("username");
|
||||
} catch(ex) {}
|
||||
|
||||
if (!username) {
|
||||
Status.login = LOGIN_FAILED_NO_USERNAME;
|
||||
return Status.service;
|
||||
let result = this._authManager.currentAuthState;
|
||||
if (result == STATUS_OK) {
|
||||
Status.service = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
if (!Utils.mpLocked()) {
|
||||
let id = ID.get("WeaveID");
|
||||
if (!id) {
|
||||
id = ID.set("WeaveID", new Identity(PWDMGR_PASSWORD_REALM, username));
|
||||
}
|
||||
|
||||
if (!id.password) {
|
||||
Status.login = LOGIN_FAILED_NO_PASSWORD;
|
||||
return Status.service;
|
||||
}
|
||||
|
||||
id = ID.get("WeaveCryptoID");
|
||||
if (!id) {
|
||||
id = ID.set("WeaveCryptoID",
|
||||
new SyncKeyBundle(PWDMGR_PASSPHRASE_REALM, username));
|
||||
}
|
||||
|
||||
if (!id.keyStr) {
|
||||
Status.login = LOGIN_FAILED_NO_PASSPHRASE;
|
||||
return Status.service;
|
||||
}
|
||||
}
|
||||
return Status.service = STATUS_OK;
|
||||
Status.login = result;
|
||||
return Status.service;
|
||||
},
|
||||
|
||||
resetBackoff: function resetBackoff() {
|
||||
|
|
|
@ -49,7 +49,6 @@ Cu.import("resource://services-sync/ext/Observers.js");
|
|||
Cu.import("resource://services-sync/ext/Preferences.js");
|
||||
Cu.import("resource://services-sync/ext/StringBundle.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
Cu.import("resource://services-sync/status.js");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
|
@ -1233,12 +1232,14 @@ let Utils = {
|
|||
* Status.backoffInterval is higher.
|
||||
*
|
||||
*/
|
||||
calculateBackoff: function calculateBackoff(attempts, base_interval) {
|
||||
calculateBackoff: function calculateBackoff(attempts, baseInterval,
|
||||
statusInterval) {
|
||||
let backoffInterval = attempts *
|
||||
(Math.floor(Math.random() * base_interval) +
|
||||
base_interval);
|
||||
return Math.max(Math.min(backoffInterval, MAXIMUM_BACKOFF_INTERVAL), Status.backoffInterval);
|
||||
}
|
||||
(Math.floor(Math.random() * baseInterval) +
|
||||
baseInterval);
|
||||
return Math.max(Math.min(backoffInterval, MAXIMUM_BACKOFF_INTERVAL),
|
||||
statusInterval);
|
||||
},
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(Utils, "_utf8Converter", function() {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/async.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
Cu.import("resource://services-sync/engines.js");
|
||||
|
@ -260,14 +261,22 @@ FakeCryptoService.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
function setBasicCredentials(username, password, syncKey) {
|
||||
let auth = Identity;
|
||||
auth.username = username;
|
||||
auth.basicPassword = password;
|
||||
auth.syncKey = syncKey;
|
||||
}
|
||||
|
||||
function SyncTestingInfrastructure() {
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
function SyncTestingInfrastructure(username, password, syncKey) {
|
||||
Cu.import("resource://services-sync/service.js");
|
||||
|
||||
ID.set('WeaveID',
|
||||
new Identity('Mozilla Services Encryption Passphrase', 'foo'));
|
||||
ID.set('WeaveCryptoID',
|
||||
new Identity('Mozilla Services Encryption Passphrase', 'foo'));
|
||||
Identity.account = username || "foo";
|
||||
Identity.basicPassword = password || "password";
|
||||
Identity.syncKey = syncKey || "foo";
|
||||
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
this.logStats = initTestLogging();
|
||||
this.fakeFilesystem = new FakeFilesystemService({});
|
||||
|
|
|
@ -64,8 +64,12 @@ function basic_auth_header(user, password) {
|
|||
}
|
||||
|
||||
function basic_auth_matches(req, user, password) {
|
||||
return req.hasHeader("Authorization") &&
|
||||
(req.getHeader("Authorization") == basic_auth_header(user, password));
|
||||
if (!req.hasHeader("Authorization")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let expected = basic_auth_header(user, Utils.encodeUTF8(password));
|
||||
return req.getHeader("Authorization") == expected;
|
||||
}
|
||||
|
||||
function httpd_basic_auth_handler(body, metadata, response) {
|
||||
|
|
|
@ -154,11 +154,7 @@ add_test(function test_disabled_install_semantics() {
|
|||
const PASSPHRASE = "abcdeabcdeabcdeabcdeabcdea";
|
||||
const ADDON_ID = "addon1@tests.mozilla.org";
|
||||
|
||||
Service.username = USER;
|
||||
Service.password = PASSWORD;
|
||||
Service.passphrase = PASSPHRASE;
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
new SyncTestingInfrastructure(USER, PASSWORD, PASSPHRASE);
|
||||
|
||||
generateNewKeys();
|
||||
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
Cu.import("resource://services-sync/resource.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
let logger;
|
||||
|
||||
function server_handler(metadata, response) {
|
||||
let body, statusCode, status;
|
||||
let guestHeader = basic_auth_header("guest", "guest");
|
||||
let johnHeader = basic_auth_header("johndoe", "moneyislike$£¥");
|
||||
|
||||
_("Guest header: " + guestHeader);
|
||||
_("John header: " + johnHeader);
|
||||
|
||||
switch (metadata.getHeader("Authorization")) {
|
||||
case guestHeader:
|
||||
body = "This path exists and is protected";
|
||||
statusCode = 200;
|
||||
status = "OK";
|
||||
break;
|
||||
case johnHeader:
|
||||
body = "This path exists and is protected by a UTF8 password";
|
||||
statusCode = 200;
|
||||
status = "OK";
|
||||
break;
|
||||
default:
|
||||
body = "This path exists and is protected - failed";
|
||||
statusCode = 401;
|
||||
status = "Unauthorized";
|
||||
}
|
||||
|
||||
response.setStatusLine(metadata.httpVersion, statusCode, status);
|
||||
response.setHeader("WWW-Authenticate", 'Basic realm="secret"', false);
|
||||
response.bodyOutputStream.write(body, body.length);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
initTestLogging("Trace");
|
||||
|
||||
do_test_pending();
|
||||
let server = new nsHttpServer();
|
||||
server.registerPathHandler("/foo", server_handler);
|
||||
server.registerPathHandler("/bar", server_handler);
|
||||
server.start(8080);
|
||||
|
||||
let guestIdentity = new Identity("secret", "guest", "guest");
|
||||
let johnIdentity = new Identity("secret2", "johndoe", "moneyislike$£¥")
|
||||
let guestAuth = new BasicAuthenticator(guestIdentity);
|
||||
let johnAuth = new BasicAuthenticator(johnIdentity);
|
||||
Auth.defaultAuthenticator = guestAuth;
|
||||
Auth.registerAuthenticator("bar$", johnAuth);
|
||||
|
||||
try {
|
||||
let content = new Resource("http://localhost:8080/foo").get();
|
||||
do_check_eq(content, "This path exists and is protected");
|
||||
do_check_eq(content.status, 200);
|
||||
|
||||
content = new Resource("http://localhost:8080/bar").get();
|
||||
do_check_eq(content, "This path exists and is protected by a UTF8 password");
|
||||
do_check_eq(content.status, 200);
|
||||
} finally {
|
||||
server.stop(do_test_finished);
|
||||
}
|
||||
}
|
|
@ -92,10 +92,7 @@ function serverForFoo(engine) {
|
|||
|
||||
add_test(function test_processIncoming_error_orderChildren() {
|
||||
_("Ensure that _orderChildren() is called even when _processIncoming() throws an error.");
|
||||
let syncTesting = new SyncTestingInfrastructure();
|
||||
Svc.Prefs.set("serverURL", TEST_SERVER_URL);
|
||||
Svc.Prefs.set("clusterURL", TEST_CLUSTER_URL);
|
||||
Svc.Prefs.set("username", "foo");
|
||||
new SyncTestingInfrastructure();
|
||||
|
||||
let engine = new BookmarksEngine();
|
||||
let store = engine._store;
|
||||
|
@ -165,10 +162,7 @@ add_test(function test_processIncoming_error_orderChildren() {
|
|||
|
||||
add_test(function test_restorePromptsReupload() {
|
||||
_("Ensure that restoring from a backup will reupload all records.");
|
||||
let syncTesting = new SyncTestingInfrastructure();
|
||||
Svc.Prefs.set("username", "foo");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
new SyncTestingInfrastructure();
|
||||
|
||||
let engine = new BookmarksEngine();
|
||||
let store = engine._store;
|
||||
|
@ -333,10 +327,7 @@ add_test(function test_mismatched_types() {
|
|||
"parentid": "toolbar"
|
||||
};
|
||||
|
||||
let syncTesting = new SyncTestingInfrastructure();
|
||||
Svc.Prefs.set("username", "foo");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
new SyncTestingInfrastructure();
|
||||
|
||||
let engine = new BookmarksEngine();
|
||||
let store = engine._store;
|
||||
|
@ -379,10 +370,8 @@ add_test(function test_mismatched_types() {
|
|||
add_test(function test_bookmark_guidMap_fail() {
|
||||
_("Ensure that failures building the GUID map cause early death.");
|
||||
|
||||
let syncTesting = new SyncTestingInfrastructure();
|
||||
Svc.Prefs.set("serverURL", TEST_SERVER_URL);
|
||||
Svc.Prefs.set("clusterURL", TEST_CLUSTER_URL);
|
||||
Svc.Prefs.set("username", "foo");
|
||||
new SyncTestingInfrastructure();
|
||||
|
||||
let engine = new BookmarksEngine();
|
||||
let store = engine._store;
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/keys.js");
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
Cu.import("resource://services-sync/engines/bookmarks.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
|
@ -11,10 +15,10 @@ function prepareBookmarkItem(collection, id) {
|
|||
}
|
||||
|
||||
function run_test() {
|
||||
let keyBundle = ID.set("WeaveCryptoID", new SyncKeyBundle(null, "john@example.com"));
|
||||
keyBundle.keyStr = "abcdeabcdeabcdeabcdeabcdea";
|
||||
|
||||
Identity.username = "john@example.com";
|
||||
Identity.syncKey = "abcdeabcdeabcdeabcdeabcdea";
|
||||
generateNewKeys();
|
||||
let keyBundle = Identity.syncKeyBundle;
|
||||
|
||||
let log = Log4Moz.repository.getLogger("Test");
|
||||
Log4Moz.repository.rootLogger.addAppender(new Log4Moz.DumpAppender());
|
||||
|
|
|
@ -58,6 +58,8 @@ function serverForFoo(engine) {
|
|||
// Verify that Places smart bookmarks have their annotation uploaded and
|
||||
// handled locally.
|
||||
add_test(function test_annotation_uploaded() {
|
||||
new SyncTestingInfrastructure();
|
||||
|
||||
let startCount = smartBookmarkCount();
|
||||
|
||||
_("Start count is " + startCount);
|
||||
|
@ -106,10 +108,6 @@ add_test(function test_annotation_uploaded() {
|
|||
do_check_eq(smartBookmarkCount(), startCount + 1);
|
||||
|
||||
_("Sync record to the server.");
|
||||
Svc.Prefs.set("username", "foo");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
let server = serverForFoo(engine);
|
||||
let collection = server.user("foo").collection("bookmarks");
|
||||
|
||||
|
@ -178,6 +176,8 @@ add_test(function test_annotation_uploaded() {
|
|||
});
|
||||
|
||||
add_test(function test_smart_bookmarks_duped() {
|
||||
new SyncTestingInfrastructure();
|
||||
|
||||
let parent = PlacesUtils.toolbarFolderId;
|
||||
let uri =
|
||||
Utils.makeURI("place:redirectsMode=" +
|
||||
|
@ -192,10 +192,6 @@ add_test(function test_smart_bookmarks_duped() {
|
|||
let record = store.createRecord(mostVisitedGUID);
|
||||
|
||||
_("Prepare sync.");
|
||||
Svc.Prefs.set("username", "foo");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
let server = serverForFoo(engine);
|
||||
let collection = server.user("foo").collection("bookmarks");
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
|
@ -48,7 +51,7 @@ add_test(function test_bad_hmac() {
|
|||
function uploadNewKeys() {
|
||||
generateNewKeys();
|
||||
let serverKeys = CollectionKeys.asWBO("crypto", "keys");
|
||||
serverKeys.encrypt(Weave.Service.syncKeyBundle);
|
||||
serverKeys.encrypt(Weave.Identity.syncKeyBundle);
|
||||
do_check_true(serverKeys.upload(Weave.Service.cryptoKeysURL).success);
|
||||
}
|
||||
|
||||
|
@ -77,7 +80,7 @@ add_test(function test_bad_hmac() {
|
|||
Clients.resetClient();
|
||||
generateNewKeys();
|
||||
let serverKeys = CollectionKeys.asWBO("crypto", "keys");
|
||||
serverKeys.encrypt(Weave.Service.syncKeyBundle);
|
||||
serverKeys.encrypt(Weave.Identity.syncKeyBundle);
|
||||
do_check_true(serverKeys.upload(Weave.Service.cryptoKeysURL).success);
|
||||
|
||||
_("Sync.");
|
||||
|
@ -165,9 +168,7 @@ add_test(function test_properties() {
|
|||
add_test(function test_sync() {
|
||||
_("Ensure that Clients engine uploads a new client record once a week.");
|
||||
|
||||
Svc.Prefs.set("serverURL", TEST_SERVER_URL);
|
||||
Svc.Prefs.set("clusterURL", TEST_CLUSTER_URL);
|
||||
Svc.Prefs.set("username", "foo");
|
||||
new SyncTestingInfrastructure();
|
||||
generateNewKeys();
|
||||
|
||||
let contents = {
|
||||
|
@ -405,9 +406,7 @@ add_test(function test_process_incoming_commands() {
|
|||
add_test(function test_command_sync() {
|
||||
_("Ensure that commands are synced across clients.");
|
||||
|
||||
Svc.Prefs.set("serverURL", TEST_SERVER_URL);
|
||||
Svc.Prefs.set("clusterURL", TEST_CLUSTER_URL);
|
||||
Svc.Prefs.set("username", "foo");
|
||||
new SyncTestingInfrastructure();
|
||||
|
||||
Clients._store.wipe();
|
||||
generateNewKeys();
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/keys.js");
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
Cu.import("resource://services-sync/engines/clients.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
|
||||
function run_test() {
|
||||
_("Set up test fixtures.");
|
||||
ID.set('WeaveID', new Identity('Some Identity', 'foo'));
|
||||
|
||||
Identity.username = "john@example.com";
|
||||
Svc.Prefs.set("clusterURL", "http://fakebase/");
|
||||
let baseUri = "http://fakebase/1.1/foo/storage/";
|
||||
let pubUri = baseUri + "keys/pubkey";
|
||||
let privUri = baseUri + "keys/privkey";
|
||||
|
||||
let keyBundle = ID.set("WeaveCryptoID",
|
||||
new SyncKeyBundle(null, "john@example.com", "abcdeabcdeabcdeabcdeabcdea"));
|
||||
Identity.syncKey = "abcdeabcdeabcdeabcdeabcdea";
|
||||
let keyBundle = Identity.syncKeyBundle;
|
||||
|
||||
try {
|
||||
_("Test that serializing client records results in uploadable ascii");
|
||||
|
|
|
@ -19,11 +19,9 @@ add_test(function test_missing_crypto_collection() {
|
|||
};
|
||||
}
|
||||
|
||||
setBasicCredentials("johndoe", "ilovejane", "a-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "a-aaaaa-aaaaa-aaaaa-aaaaa-aaaaa";
|
||||
|
||||
let handlers = {
|
||||
"/1.1/johndoe/info/collections": maybe_empty(johnHelper.handler),
|
||||
|
|
|
@ -51,12 +51,9 @@ add_test(function test_locally_changed_keys() {
|
|||
getBrowserState: function () JSON.stringify(myTabs)
|
||||
};
|
||||
|
||||
Weave.Service.username = "johndoe";
|
||||
Weave.Service.password = "ilovejane";
|
||||
Weave.Service.passphrase = passphrase;
|
||||
|
||||
Weave.Service.serverURL = TEST_SERVER_URL;
|
||||
Weave.Service.clusterURL = TEST_CLUSTER_URL;
|
||||
setBasicCredentials("johndoe", "password", passphrase);
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
Engines.register(HistoryEngine);
|
||||
Weave.Service._registerEngines();
|
||||
|
@ -79,7 +76,7 @@ add_test(function test_locally_changed_keys() {
|
|||
// Upload keys.
|
||||
generateNewKeys();
|
||||
let serverKeys = CollectionKeys.asWBO("crypto", "keys");
|
||||
serverKeys.encrypt(Weave.Service.syncKeyBundle);
|
||||
serverKeys.encrypt(Weave.Identity.syncKeyBundle);
|
||||
do_check_true(serverKeys.upload(Weave.Service.cryptoKeysURL).success);
|
||||
|
||||
// Check that login works.
|
||||
|
|
|
@ -3,10 +3,7 @@ Cu.import("resource://services-sync/util.js");
|
|||
|
||||
add_test(function test_processIncoming_abort() {
|
||||
_("An abort exception, raised in applyIncoming, will abort _processIncoming.");
|
||||
let syncTesting = new SyncTestingInfrastructure();
|
||||
Svc.Prefs.set("serverURL", TEST_SERVER_URL);
|
||||
Svc.Prefs.set("clusterURL", TEST_CLUSTER_URL);
|
||||
Svc.Prefs.set("username", "foo");
|
||||
new SyncTestingInfrastructure();
|
||||
generateNewKeys();
|
||||
|
||||
let engine = new RotaryEngine();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
Cu.import("resource://services-sync/engines/clients.js");
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/keys.js");
|
||||
Cu.import("resource://services-sync/policies.js");
|
||||
Cu.import("resource://services-sync/status.js");
|
||||
|
||||
|
@ -52,8 +53,7 @@ function run_test() {
|
|||
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(PWDMGR_PASSPHRASE_REALM, Service.username);
|
||||
newSyncKeyBundle.keyStr = "23456234562345623456234562";
|
||||
let newSyncKeyBundle = new SyncKeyBundle("johndoe", "23456234562345623456234562");
|
||||
let keys = CollectionKeys.asWBO();
|
||||
keys.encrypt(newSyncKeyBundle);
|
||||
keys.upload(Service.cryptoKeysURL);
|
||||
|
@ -118,9 +118,7 @@ function sync_httpd_setup() {
|
|||
}
|
||||
|
||||
function setUp() {
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("johndoe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
|
@ -130,7 +128,7 @@ function setUp() {
|
|||
function generateAndUploadKeys() {
|
||||
generateNewKeys();
|
||||
let serverKeys = CollectionKeys.asWBO("crypto", "keys");
|
||||
serverKeys.encrypt(Service.syncKeyBundle);
|
||||
serverKeys.encrypt(Identity.syncKeyBundle);
|
||||
return serverKeys.upload(Service.cryptoKeysURL).success;
|
||||
}
|
||||
|
||||
|
@ -172,7 +170,8 @@ add_test(function test_401_logout() {
|
|||
}
|
||||
|
||||
// Make sync fail due to login rejected.
|
||||
Service.username = "janedoe";
|
||||
setBasicCredentials("janedoe", "irrelevant", "irrelevant");
|
||||
Service._updateCachedURLs();
|
||||
|
||||
_("Starting first sync.");
|
||||
Service.sync();
|
||||
|
@ -425,7 +424,7 @@ add_test(function test_login_syncAndReportErrors_non_network_error() {
|
|||
// when calling syncAndReportErrors
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
Service.password = "";
|
||||
Identity.basicPassword = null;
|
||||
|
||||
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:login:error", onSyncError);
|
||||
|
@ -469,7 +468,7 @@ add_test(function test_login_syncAndReportErrors_prolonged_non_network_error() {
|
|||
// reported when calling syncAndReportErrors.
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
Service.password = "";
|
||||
Identity.basicPassword = null;
|
||||
|
||||
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:login:error", onSyncError);
|
||||
|
@ -510,9 +509,7 @@ add_test(function test_sync_syncAndReportErrors_prolonged_non_network_error() {
|
|||
|
||||
add_test(function test_login_syncAndReportErrors_network_error() {
|
||||
// Test network errors are reported when calling syncAndReportErrors.
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("broken.wipe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
|
@ -549,9 +546,7 @@ add_test(function test_sync_syncAndReportErrors_network_error() {
|
|||
add_test(function test_login_syncAndReportErrors_prolonged_network_error() {
|
||||
// Test prolonged, network errors are reported
|
||||
// when calling syncAndReportErrors.
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("johndoe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
|
@ -589,7 +584,7 @@ add_test(function test_login_prolonged_non_network_error() {
|
|||
// Test prolonged, non-network errors are reported
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
Service.password = "";
|
||||
Identity.basicPassword = null;
|
||||
|
||||
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:login:error", onSyncError);
|
||||
|
@ -629,9 +624,7 @@ add_test(function test_sync_prolonged_non_network_error() {
|
|||
|
||||
add_test(function test_login_prolonged_network_error() {
|
||||
// Test prolonged, network errors are reported
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("johndoe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
|
@ -668,7 +661,7 @@ add_test(function test_login_non_network_error() {
|
|||
// Test non-network errors are reported
|
||||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
Service.password = "";
|
||||
Identity.basicPassword = null;
|
||||
|
||||
Svc.Obs.add("weave:ui:login:error", function onSyncError() {
|
||||
Svc.Obs.remove("weave:ui:login:error", onSyncError);
|
||||
|
@ -707,9 +700,7 @@ add_test(function test_sync_non_network_error() {
|
|||
});
|
||||
|
||||
add_test(function test_login_network_error() {
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("johndoe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
|
@ -784,6 +775,7 @@ add_test(function test_info_collections_login_server_maintenance_error() {
|
|||
setUp();
|
||||
|
||||
Service.username = "broken.info";
|
||||
setBasicCredentials("broken.info", "irrelevant", "irrelevant");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
|
@ -794,7 +786,7 @@ add_test(function test_info_collections_login_server_maintenance_error() {
|
|||
});
|
||||
|
||||
function onUIUpdate() {
|
||||
do_throw("Shouldn't get here!");
|
||||
do_throw("Shouldn't experience UI update!");
|
||||
}
|
||||
Svc.Obs.add("weave:ui:login:error", onUIUpdate);
|
||||
|
||||
|
@ -823,7 +815,7 @@ add_test(function test_meta_global_login_server_maintenance_error() {
|
|||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
Service.username = "broken.meta";
|
||||
setBasicCredentials("broken.meta", "irrelevant", "irrelevant");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
|
@ -863,9 +855,10 @@ add_test(function test_crypto_keys_login_server_maintenance_error() {
|
|||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
Service.username = "broken.keys";
|
||||
setBasicCredentials("broken.keys", "irrelevant", "irrelevant");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
// Force re-download of keys
|
||||
CollectionKeys.clear();
|
||||
|
||||
|
@ -931,7 +924,7 @@ add_test(function test_info_collections_login_prolonged_server_maintenance_error
|
|||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
Service.username = "broken.info";
|
||||
setBasicCredentials("broken.info", "irrelevant", "irrelevant");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
|
@ -964,7 +957,7 @@ add_test(function test_meta_global_login_prolonged_server_maintenance_error(){
|
|||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
Service.username = "broken.meta";
|
||||
setBasicCredentials("broken.meta", "irrelevant", "irrelevant");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
|
@ -997,7 +990,7 @@ add_test(function test_download_crypto_keys_login_prolonged_server_maintenance_e
|
|||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
Service.username = "broken.keys";
|
||||
setBasicCredentials("broken.keys", "irrelevant", "irrelevant");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
// Force re-download of keys
|
||||
|
@ -1032,9 +1025,7 @@ add_test(function test_upload_crypto_keys_login_prolonged_server_maintenance_err
|
|||
let server = sync_httpd_setup();
|
||||
|
||||
// Start off with an empty account, do not upload a key.
|
||||
Service.username = "broken.keys";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("broken.keys", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
|
@ -1068,9 +1059,7 @@ add_test(function test_wipeServer_login_prolonged_server_maintenance_error(){
|
|||
let server = sync_httpd_setup();
|
||||
|
||||
// Start off with an empty account, do not upload a key.
|
||||
Service.username = "broken.wipe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("broken.wipe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
|
@ -1103,9 +1092,8 @@ add_test(function test_wipeRemote_prolonged_server_maintenance_error(){
|
|||
// wiping all remote devices.
|
||||
let server = sync_httpd_setup();
|
||||
|
||||
Service.username = "broken.wipe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
server.registerPathHandler("/1.1/broken.wipe/storage/catapult", service_unavailable);
|
||||
setBasicCredentials("broken.wipe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
generateAndUploadKeys();
|
||||
|
@ -1173,7 +1161,7 @@ add_test(function test_info_collections_login_syncAndReportErrors_server_mainten
|
|||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
Service.username = "broken.info";
|
||||
setBasicCredentials("broken.info", "irrelevant", "irrelevant");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
|
@ -1207,7 +1195,7 @@ add_test(function test_meta_global_login_syncAndReportErrors_server_maintenance_
|
|||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
Service.username = "broken.meta";
|
||||
setBasicCredentials("broken.meta", "irrelevant", "irrelevant");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
|
@ -1241,7 +1229,7 @@ add_test(function test_download_crypto_keys_login_syncAndReportErrors_server_mai
|
|||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
Service.username = "broken.keys";
|
||||
setBasicCredentials("broken.keys", "irrelevant", "irrelevant");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
// Force re-download of keys
|
||||
|
@ -1277,9 +1265,7 @@ add_test(function test_upload_crypto_keys_login_syncAndReportErrors_server_maint
|
|||
let server = sync_httpd_setup();
|
||||
|
||||
// Start off with an empty account, do not upload a key.
|
||||
Service.username = "broken.keys";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("broken.keys", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
|
@ -1313,9 +1299,7 @@ add_test(function test_wipeServer_login_syncAndReportErrors_server_maintenance_e
|
|||
let server = sync_httpd_setup();
|
||||
|
||||
// Start off with an empty account, do not upload a key.
|
||||
Service.username = "broken.wipe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("broken.wipe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
|
@ -1348,9 +1332,7 @@ add_test(function test_wipeRemote_syncAndReportErrors_server_maintenance_error()
|
|||
// wiping all remote devices.
|
||||
let server = sync_httpd_setup();
|
||||
|
||||
Service.username = "broken.wipe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("broken.wipe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
generateAndUploadKeys();
|
||||
|
@ -1418,7 +1400,7 @@ add_test(function test_info_collections_login_syncAndReportErrors_prolonged_serv
|
|||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
Service.username = "broken.info";
|
||||
setBasicCredentials("broken.info", "irrelevant", "irrelevant");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
|
@ -1452,7 +1434,7 @@ add_test(function test_meta_global_login_syncAndReportErrors_prolonged_server_ma
|
|||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
Service.username = "broken.meta";
|
||||
setBasicCredentials("broken.meta", "irrelevant", "irrelevant");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
|
@ -1486,7 +1468,7 @@ add_test(function test_download_crypto_keys_login_syncAndReportErrors_prolonged_
|
|||
let server = sync_httpd_setup();
|
||||
setUp();
|
||||
|
||||
Service.username = "broken.keys";
|
||||
setBasicCredentials("broken.keys", "irrelevant", "irrelevant");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
// Force re-download of keys
|
||||
|
@ -1522,9 +1504,7 @@ add_test(function test_upload_crypto_keys_login_syncAndReportErrors_prolonged_se
|
|||
let server = sync_httpd_setup();
|
||||
|
||||
// Start off with an empty account, do not upload a key.
|
||||
Service.username = "broken.keys";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("broken.keys", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
|
@ -1558,9 +1538,7 @@ add_test(function test_wipeServer_login_syncAndReportErrors_prolonged_server_mai
|
|||
let server = sync_httpd_setup();
|
||||
|
||||
// Start off with an empty account, do not upload a key.
|
||||
Service.username = "broken.wipe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("broken.wipe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_MAINTENANCE_URL;
|
||||
Service.clusterURL = TEST_MAINTENANCE_URL;
|
||||
|
||||
|
|
|
@ -48,9 +48,7 @@ function sync_httpd_setup() {
|
|||
}
|
||||
|
||||
function setUp() {
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "aabcdeabcdeabcdeabcdeabcde";
|
||||
setBasicCredentials("johndoe", "ilovejane", "aabcdeabcdeabcdeabcdeabcde");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
new FakeCryptoService();
|
||||
|
@ -59,7 +57,7 @@ function setUp() {
|
|||
function generateAndUploadKeys() {
|
||||
generateNewKeys();
|
||||
let serverKeys = CollectionKeys.asWBO("crypto", "keys");
|
||||
serverKeys.encrypt(Weave.Service.syncKeyBundle);
|
||||
serverKeys.encrypt(Weave.Identity.syncKeyBundle);
|
||||
return serverKeys.upload("http://localhost:8080/1.1/johndoe/storage/crypto/keys").success;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
Cu.import("resource://services-sync/engines/history.js");
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
|
@ -5,16 +8,13 @@ Cu.import("resource://services-sync/engines.js");
|
|||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
var syncTesting = new SyncTestingInfrastructure();
|
||||
|
||||
add_test(function test_processIncoming_mobile_history_batched() {
|
||||
_("SyncEngine._processIncoming works on history engine.");
|
||||
|
||||
let FAKE_DOWNLOAD_LIMIT = 100;
|
||||
|
||||
Svc.Prefs.set("serverURL", TEST_SERVER_URL);
|
||||
Svc.Prefs.set("clusterURL", TEST_CLUSTER_URL);
|
||||
Svc.Prefs.set("username", "foo");
|
||||
new SyncTestingInfrastructure();
|
||||
|
||||
Svc.Prefs.set("client.type", "mobile");
|
||||
PlacesUtils.history.removeAllPages();
|
||||
Engines.register(HistoryEngine);
|
||||
|
|
|
@ -18,11 +18,9 @@ function shared_setup() {
|
|||
hmacErrorCount = 0;
|
||||
|
||||
// Do not instantiate SyncTestingInfrastructure; we need real crypto.
|
||||
setBasicCredentials("foo", "foo", "aabcdeabcdeabcdeabcdeabcde");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
Service.username = "foo";
|
||||
Service.password = "foo";
|
||||
Service.passphrase = "aabcdeabcdeabcdeabcdeabcde";
|
||||
|
||||
// Make sure RotaryEngine is the only one we sync.
|
||||
Engines._engines = {};
|
||||
|
|
|
@ -0,0 +1,226 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
|
||||
function run_test() {
|
||||
initTestLogging("Trace");
|
||||
Log4Moz.repository.getLogger("Sync.Identity").level =
|
||||
Log4Moz.Level.Trace;
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_test(function test_username_from_account() {
|
||||
_("Ensure usernameFromAccount works properly.");
|
||||
|
||||
do_check_eq(Identity.usernameFromAccount(null), null);
|
||||
do_check_eq(Identity.usernameFromAccount("user"), "user");
|
||||
do_check_eq(Identity.usernameFromAccount("User"), "user");
|
||||
do_check_eq(Identity.usernameFromAccount("john@doe.com"),
|
||||
"7wohs32cngzuqt466q3ge7indszva4of");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_account_username() {
|
||||
_("Ensure the account and username attributes work properly.");
|
||||
|
||||
_("Verify initial state");
|
||||
do_check_eq(Svc.Prefs.get("account"), undefined);
|
||||
do_check_eq(Svc.Prefs.get("username"), undefined);
|
||||
do_check_eq(Identity.account, null);
|
||||
do_check_eq(Identity.username, null);
|
||||
|
||||
_("The 'username' attribute is normalized to lower case, updates preferences and identities.");
|
||||
Identity.username = "TarZan";
|
||||
do_check_eq(Identity.username, "tarzan");
|
||||
do_check_eq(Svc.Prefs.get("username"), "tarzan");
|
||||
do_check_eq(Identity.username, "tarzan");
|
||||
|
||||
_("If not set, the 'account attribute' falls back to the username for backwards compatibility.");
|
||||
do_check_eq(Identity.account, "tarzan");
|
||||
|
||||
_("Setting 'username' to a non-truthy value resets the pref.");
|
||||
Identity.username = null;
|
||||
do_check_eq(Identity.username, null);
|
||||
do_check_eq(Identity.account, null);
|
||||
const default_marker = {};
|
||||
do_check_eq(Svc.Prefs.get("username", default_marker), default_marker);
|
||||
do_check_eq(Identity.username, null);
|
||||
|
||||
_("The 'account' attribute will set the 'username' if it doesn't contain characters that aren't allowed in the username.");
|
||||
Identity.account = "johndoe";
|
||||
do_check_eq(Identity.account, "johndoe");
|
||||
do_check_eq(Identity.username, "johndoe");
|
||||
do_check_eq(Svc.Prefs.get("username"), "johndoe");
|
||||
do_check_eq(Identity.username, "johndoe");
|
||||
|
||||
_("If 'account' contains disallowed characters such as @, 'username' will the base32 encoded SHA1 hash of 'account'");
|
||||
Identity.account = "John@Doe.com";
|
||||
do_check_eq(Identity.account, "john@doe.com");
|
||||
do_check_eq(Identity.username, "7wohs32cngzuqt466q3ge7indszva4of");
|
||||
|
||||
_("Setting 'account' to a non-truthy value resets the pref.");
|
||||
Identity.account = null;
|
||||
do_check_eq(Identity.account, null);
|
||||
do_check_eq(Svc.Prefs.get("account", default_marker), default_marker);
|
||||
do_check_eq(Identity.username, null);
|
||||
do_check_eq(Svc.Prefs.get("username", default_marker), default_marker);
|
||||
|
||||
Svc.Prefs.resetBranch("");
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_basic_password() {
|
||||
_("Ensure basic password setting works as expected.");
|
||||
|
||||
Identity.account = null;
|
||||
do_check_eq(Identity.currentAuthState, LOGIN_FAILED_NO_USERNAME);
|
||||
let thrown = false;
|
||||
try {
|
||||
Identity.basicPassword = "foobar";
|
||||
} catch (ex) {
|
||||
thrown = true;
|
||||
}
|
||||
|
||||
do_check_true(thrown);
|
||||
thrown = false;
|
||||
|
||||
Identity.account = "johndoe";
|
||||
do_check_eq(Identity.currentAuthState, LOGIN_FAILED_NO_PASSWORD);
|
||||
Identity.basicPassword = "password";
|
||||
do_check_eq(Identity.basicPassword, "password");
|
||||
do_check_eq(Identity.currentAuthState, LOGIN_FAILED_NO_PASSPHRASE);
|
||||
do_check_true(Identity.hasBasicCredentials());
|
||||
|
||||
Identity.account = null;
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_basic_password_persistence() {
|
||||
_("Ensure credentials are saved and restored to the login manager properly.");
|
||||
|
||||
// Just in case.
|
||||
Identity.account = null;
|
||||
Identity.deleteSyncCredentials();
|
||||
|
||||
Identity.account = "janesmith";
|
||||
Identity.basicPassword = "ilovejohn";
|
||||
Identity.persistCredentials();
|
||||
|
||||
let im1 = new IdentityManager();
|
||||
do_check_eq(im1._basicPassword, null);
|
||||
do_check_eq(im1.username, "janesmith");
|
||||
do_check_eq(im1.basicPassword, "ilovejohn");
|
||||
|
||||
let im2 = new IdentityManager();
|
||||
do_check_eq(im2._basicPassword, null);
|
||||
|
||||
_("Now remove the password and ensure it is deleted from storage.");
|
||||
Identity.basicPassword = null;
|
||||
Identity.persistCredentials(); // This should nuke from storage.
|
||||
do_check_eq(im2.basicPassword, null);
|
||||
|
||||
_("Ensure that retrieving an unset but unpersisted removal returns null.");
|
||||
Identity.account = "janesmith";
|
||||
Identity.basicPassword = "myotherpassword";
|
||||
Identity.persistCredentials();
|
||||
|
||||
Identity.basicPassword = null;
|
||||
do_check_eq(Identity.basicPassword, null);
|
||||
|
||||
// Reset for next test.
|
||||
Identity.account = null;
|
||||
Identity.persistCredentials();
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_sync_key() {
|
||||
_("Ensure Sync Key works as advertised.");
|
||||
|
||||
_("Ensure setting a Sync Key before an account throws.");
|
||||
let thrown = false;
|
||||
try {
|
||||
Identity.syncKey = "blahblah";
|
||||
} catch (ex) {
|
||||
thrown = true;
|
||||
}
|
||||
do_check_true(thrown);
|
||||
thrown = false;
|
||||
|
||||
Identity.account = "johnsmith";
|
||||
Identity.basicPassword = "johnsmithpw";
|
||||
|
||||
do_check_eq(Identity.syncKey, null);
|
||||
do_check_eq(Identity.syncKeyBundle, null);
|
||||
|
||||
_("An invalid Sync Key is silently accepted for historical reasons.");
|
||||
Identity.syncKey = "synckey";
|
||||
do_check_eq(Identity.syncKey, "synckey");
|
||||
|
||||
_("But the SyncKeyBundle should not be created from bad keys.");
|
||||
do_check_eq(Identity.syncKeyBundle, null);
|
||||
|
||||
let syncKey = Utils.generatePassphrase();
|
||||
Identity.syncKey = syncKey;
|
||||
do_check_eq(Identity.syncKey, syncKey);
|
||||
do_check_neq(Identity.syncKeyBundle, null);
|
||||
|
||||
let im = new IdentityManager();
|
||||
im.account = "pseudojohn";
|
||||
do_check_eq(im.syncKey, null);
|
||||
do_check_eq(im.syncKeyBundle, null);
|
||||
|
||||
Identity.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;
|
||||
|
||||
Identity.persistCredentials();
|
||||
|
||||
let im = new IdentityManager();
|
||||
im.account = "pseudojohn";
|
||||
do_check_eq(im.syncKey, syncKey);
|
||||
do_check_neq(im.syncKeyBundle, null);
|
||||
|
||||
let kb1 = Identity.syncKeyBundle;
|
||||
let kb2 = im.syncKeyBundle;
|
||||
|
||||
do_check_eq(kb1.encryptionKeyB64, kb2.encryptionKeyB64);
|
||||
do_check_eq(kb1.hmacKeyB64, kb2.hmacKeyB64);
|
||||
|
||||
Identity.account = null;
|
||||
Identity.persistCredentials();
|
||||
|
||||
let im2 = new IdentityManager();
|
||||
im2.account = "pseudojohn";
|
||||
do_check_eq(im2.syncKey, null);
|
||||
|
||||
im2.account = null;
|
||||
|
||||
_("Ensure deleted but not persisted value is retrieved.");
|
||||
Identity.account = "someoneelse";
|
||||
Identity.syncKey = Utils.generatePassphrase();
|
||||
Identity.persistCredentials();
|
||||
Identity.syncKey = null;
|
||||
do_check_eq(Identity.syncKey, null);
|
||||
|
||||
// Clean up.
|
||||
Identity.account = null;
|
||||
Identity.persistCredentials();
|
||||
|
||||
run_next_test();
|
||||
});
|
|
@ -32,15 +32,13 @@ function sync_httpd_setup() {
|
|||
}
|
||||
|
||||
function setUp() {
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("johndoe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
generateNewKeys();
|
||||
let serverKeys = CollectionKeys.asWBO("crypto", "keys");
|
||||
serverKeys.encrypt(Service.syncKeyBundle);
|
||||
serverKeys.encrypt(Identity.syncKeyBundle);
|
||||
return serverKeys.upload(Service.cryptoKeysURL);
|
||||
}
|
||||
|
||||
|
|
|
@ -183,9 +183,7 @@ function run_test() {
|
|||
|
||||
// Simulate Sync setup with credentials in place. We want to make
|
||||
// sure the J-PAKE requests don't include those data.
|
||||
let id = new Identity(PWDMGR_PASSWORD_REALM, "johndoe");
|
||||
id.password = "ilovejane";
|
||||
ID.set("WeaveID", id);
|
||||
setBasicCredentials("johndoe", "ilovejane");
|
||||
|
||||
server = httpd_setup({"/new_channel": server_new_channel,
|
||||
"/report": server_report});
|
||||
|
|
|
@ -1,18 +1,33 @@
|
|||
var btoa;
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
btoa = Cu.import("resource://services-sync/util.js").btoa;
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/keys.js");
|
||||
|
||||
function sha256HMAC(message, key) {
|
||||
let h = Utils.makeHMACHasher(Ci.nsICryptoHMAC.SHA256, key);
|
||||
return Utils.digestBytes(message, h);
|
||||
}
|
||||
|
||||
function do_check_array_eq(a1, a2) {
|
||||
do_check_eq(a1.length, a2.length);
|
||||
for (let i = 0; i < a1.length; ++i) {
|
||||
do_check_eq(a1[i], a2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function do_check_keypair_eq(a, b) {
|
||||
do_check_eq(2, a.length);
|
||||
do_check_eq(2, b.length);
|
||||
do_check_eq(a[0], b[0]);
|
||||
do_check_eq(a[1], b[1]);
|
||||
}
|
||||
|
||||
function test_time_keyFromString(iterations) {
|
||||
let k;
|
||||
let o;
|
||||
let b = new BulkKeyBundle();
|
||||
let b = new BulkKeyBundle("dummy");
|
||||
let d = Utils.decodeKeyBase32("ababcdefabcdefabcdefabcdef");
|
||||
b.generateRandom();
|
||||
|
||||
|
@ -25,24 +40,109 @@ function test_time_keyFromString(iterations) {
|
|||
_("Done.");
|
||||
}
|
||||
|
||||
function test_repeated_hmac() {
|
||||
add_test(function test_set_invalid_values() {
|
||||
_("Ensure that setting invalid encryption and HMAC key values is caught.");
|
||||
|
||||
let bundle = new BulkKeyBundle("foo");
|
||||
|
||||
let thrown = false;
|
||||
try {
|
||||
bundle.encryptionKey = null;
|
||||
} catch (ex) {
|
||||
thrown = true;
|
||||
do_check_eq(ex.message.indexOf("Encryption key can only be set to"), 0);
|
||||
} finally {
|
||||
do_check_true(thrown);
|
||||
thrown = false;
|
||||
}
|
||||
|
||||
try {
|
||||
bundle.encryptionKey = ["trollololol"];
|
||||
} catch (ex) {
|
||||
thrown = true;
|
||||
do_check_eq(ex.message.indexOf("Encryption key can only be set to"), 0);
|
||||
} finally {
|
||||
do_check_true(thrown);
|
||||
thrown = false;
|
||||
}
|
||||
|
||||
try {
|
||||
bundle.hmacKey = Utils.generateRandomBytes(15);
|
||||
} catch (ex) {
|
||||
thrown = true;
|
||||
do_check_eq(ex.message.indexOf("HMAC key must be at least 128"), 0);
|
||||
} finally {
|
||||
do_check_true(thrown);
|
||||
thrown = false;
|
||||
}
|
||||
|
||||
try {
|
||||
bundle.hmacKey = null;
|
||||
} catch (ex) {
|
||||
thrown = true;
|
||||
do_check_eq(ex.message.indexOf("HMAC key can only be set to string"), 0);
|
||||
} finally {
|
||||
do_check_true(thrown);
|
||||
thrown = false;
|
||||
}
|
||||
|
||||
try {
|
||||
bundle.hmacKey = ["trollolol"];
|
||||
} catch (ex) {
|
||||
thrown = true;
|
||||
do_check_eq(ex.message.indexOf("HMAC key can only be set to"), 0);
|
||||
} finally {
|
||||
do_check_true(thrown);
|
||||
thrown = false;
|
||||
}
|
||||
|
||||
try {
|
||||
bundle.hmacKey = Utils.generateRandomBytes(15);
|
||||
} catch (ex) {
|
||||
thrown = true;
|
||||
do_check_eq(ex.message.indexOf("HMAC key must be at least 128"), 0);
|
||||
} finally {
|
||||
do_check_true(thrown);
|
||||
thrown = false;
|
||||
}
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_repeated_hmac() {
|
||||
let testKey = "ababcdefabcdefabcdefabcdef";
|
||||
let k = Utils.makeHMACKey("foo");
|
||||
let one = sha256HMAC(Utils.decodeKeyBase32(testKey), k);
|
||||
let two = sha256HMAC(Utils.decodeKeyBase32(testKey), k);
|
||||
do_check_eq(one, two);
|
||||
}
|
||||
|
||||
function do_check_array_eq(a1, a2) {
|
||||
do_check_eq(a1.length, a2.length);
|
||||
for (let i = 0; i < a1.length; ++i) {
|
||||
do_check_eq(a1[i], a2[i]);
|
||||
}
|
||||
}
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
function test_keymanager() {
|
||||
add_test(function test_sync_key_bundle_derivation() {
|
||||
_("Ensure derivation from known values works.");
|
||||
|
||||
// The known values in this test were originally verified against Firefox
|
||||
// Home.
|
||||
let bundle = new SyncKeyBundle("st3fan", "q7ynpwq7vsc9m34hankbyi3s3i");
|
||||
|
||||
// These should be compared to the results from Home, as they once were.
|
||||
let e = "14b8c09fa84e92729ee695160af6e0385f8f6215a25d14906e1747bdaa2de426";
|
||||
let h = "370e3566245d79fe602a3adb5137e42439cd2a571235197e0469d7d541b07875";
|
||||
|
||||
let realE = Utils.bytesAsHex(bundle.encryptionKey);
|
||||
let realH = Utils.bytesAsHex(bundle.hmacKey);
|
||||
|
||||
_("Real E: " + realE);
|
||||
_("Real H: " + realH);
|
||||
do_check_eq(realH, h);
|
||||
do_check_eq(realE, e);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_keymanager() {
|
||||
let testKey = "ababcdefabcdefabcdefabcdef";
|
||||
|
||||
let username = "john@example.com";
|
||||
|
||||
// Decode the key here to mirror what generateEntry will do,
|
||||
|
@ -56,28 +156,25 @@ function test_keymanager() {
|
|||
let hmacKey = sha256HMAC(sha256inputH, key);
|
||||
|
||||
// Encryption key is stored in base64 for WeaveCrypto convenience.
|
||||
do_check_eq(btoa(encryptKey), new SyncKeyBundle(null, username, testKey).encryptionKey);
|
||||
do_check_eq(hmacKey, new SyncKeyBundle(null, username, testKey).hmacKey);
|
||||
do_check_eq(encryptKey, new SyncKeyBundle(username, testKey).encryptionKey);
|
||||
do_check_eq(hmacKey, new SyncKeyBundle(username, testKey).hmacKey);
|
||||
|
||||
// Test with the same KeyBundle for both.
|
||||
let obj = new SyncKeyBundle(null, username, testKey);
|
||||
let obj = new SyncKeyBundle(username, testKey);
|
||||
do_check_eq(hmacKey, obj.hmacKey);
|
||||
do_check_eq(btoa(encryptKey), obj.encryptionKey);
|
||||
}
|
||||
do_check_eq(encryptKey, obj.encryptionKey);
|
||||
|
||||
function do_check_keypair_eq(a, b) {
|
||||
do_check_eq(2, a.length);
|
||||
do_check_eq(2, b.length);
|
||||
do_check_eq(a[0], b[0]);
|
||||
do_check_eq(a[1], b[1]);
|
||||
}
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
function test_collections_manager() {
|
||||
add_test(function test_collections_manager() {
|
||||
let log = Log4Moz.repository.getLogger("Test");
|
||||
Log4Moz.repository.rootLogger.addAppender(new Log4Moz.DumpAppender());
|
||||
|
||||
let keyBundle = ID.set("WeaveCryptoID",
|
||||
new SyncKeyBundle(PWDMGR_PASSPHRASE_REALM, "john@example.com", "a-bbbbb-ccccc-ddddd-eeeee-fffff"));
|
||||
Identity.account = "john@example.com";
|
||||
Identity.syncKey = "a-bbbbb-ccccc-ddddd-eeeee-fffff";
|
||||
|
||||
let keyBundle = Identity.syncKeyBundle;
|
||||
|
||||
/*
|
||||
* Build a test version of storage/crypto/keys.
|
||||
|
@ -143,8 +240,8 @@ function test_collections_manager() {
|
|||
* Test that we get the right keys out when we ask for
|
||||
* a collection's tokens.
|
||||
*/
|
||||
let b1 = new BulkKeyBundle(null, "bookmarks");
|
||||
b1.keyPair = [bookmarks_key64, bookmarks_hmac64];
|
||||
let b1 = new BulkKeyBundle("bookmarks");
|
||||
b1.keyPairB64 = [bookmarks_key64, bookmarks_hmac64];
|
||||
let b2 = CollectionKeys.keyForCollection("bookmarks");
|
||||
do_check_keypair_eq(b1.keyPair, b2.keyPair);
|
||||
|
||||
|
@ -152,8 +249,8 @@ function test_collections_manager() {
|
|||
do_check_true(b1.equals(b2));
|
||||
do_check_true(b2.equals(b1));
|
||||
|
||||
b1 = new BulkKeyBundle(null, "[default]");
|
||||
b1.keyPair = [default_key64, default_hmac64];
|
||||
b1 = new BulkKeyBundle("[default]");
|
||||
b1.keyPairB64 = [default_key64, default_hmac64];
|
||||
|
||||
do_check_false(b1.equals(b2));
|
||||
do_check_false(b2.equals(b1));
|
||||
|
@ -178,7 +275,7 @@ function test_collections_manager() {
|
|||
* Check _compareKeyBundleCollections.
|
||||
*/
|
||||
function newBundle(name) {
|
||||
let r = new BulkKeyBundle(null, name);
|
||||
let r = new BulkKeyBundle(name);
|
||||
r.generateRandom();
|
||||
return r;
|
||||
}
|
||||
|
@ -218,43 +315,13 @@ function test_collections_manager() {
|
|||
do_check_array_eq(d4.changed, ["bar", "foo"]);
|
||||
do_check_array_eq(d5.changed, ["baz", "foo"]);
|
||||
do_check_array_eq(d6.changed, ["bar", "foo"]);
|
||||
}
|
||||
|
||||
// Make sure that KeyBundles work when persisted through Identity.
|
||||
function test_key_persistence() {
|
||||
_("Testing key persistence.");
|
||||
|
||||
// Create our sync key bundle and persist it.
|
||||
let k = new SyncKeyBundle(null, null, "abcdeabcdeabcdeabcdeabcdea");
|
||||
k.username = "john@example.com";
|
||||
ID.set("WeaveCryptoID", k);
|
||||
let id = ID.get("WeaveCryptoID");
|
||||
do_check_eq(k, id);
|
||||
id.persist();
|
||||
|
||||
// Now erase any memory of it.
|
||||
ID.del("WeaveCryptoID");
|
||||
k = id = null;
|
||||
|
||||
// Now recreate via the persisted value.
|
||||
id = new SyncKeyBundle();
|
||||
id.username = "john@example.com";
|
||||
|
||||
// The password should have been fetched from storage...
|
||||
do_check_eq(id.password, "abcdeabcdeabcdeabcdeabcdea");
|
||||
|
||||
// ... and we should be able to grab these by derivation.
|
||||
do_check_true(!!id.hmacKeyObject);
|
||||
do_check_true(!!id.hmacKey);
|
||||
do_check_true(!!id.encryptionKey);
|
||||
}
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
test_keymanager();
|
||||
test_collections_manager();
|
||||
test_key_persistence();
|
||||
test_repeated_hmac();
|
||||
|
||||
// Only do 1,000 to avoid a 5-second pause in test runs.
|
||||
test_time_keyFromString(1000);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ const modules = [
|
|||
"ext/Preferences.js",
|
||||
"identity.js",
|
||||
"jpakeclient.js",
|
||||
"keys.js",
|
||||
"log4moz.js",
|
||||
"main.js",
|
||||
"notifications.js",
|
||||
|
|
|
@ -73,9 +73,7 @@ function installNodeHandler(server, next) {
|
|||
}
|
||||
|
||||
function prepareServer() {
|
||||
Service.username = "johndoe";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
Service.password = "ilovejane";
|
||||
setBasicCredentials("johndoe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/keys.js");
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
Cu.import("resource://services-sync/resource.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
let cryptoWrap;
|
||||
|
@ -26,8 +30,9 @@ function run_test() {
|
|||
let server;
|
||||
do_test_pending();
|
||||
|
||||
let keyBundle = ID.set("WeaveCryptoID", new SyncKeyBundle(PWDMGR_PASSPHRASE_REALM, "john@example.com"));
|
||||
keyBundle.keyStr = "a-abcde-abcde-abcde-abcde-abcde";
|
||||
Identity.username = "john@example.com";
|
||||
Identity.syncKey = "a-abcde-abcde-abcde-abcde-abcde";
|
||||
let keyBundle = Identity.syncKeyBundle;
|
||||
|
||||
try {
|
||||
let log = Log4Moz.repository.getLogger("Test");
|
||||
|
@ -37,9 +42,6 @@ function run_test() {
|
|||
|
||||
server = httpd_setup({"/steam/resource": crypted_resource_handler});
|
||||
|
||||
let auth = new BasicAuthenticator(new Identity("secret", "guest", "guest"));
|
||||
Auth.defaultAuthenticator = auth;
|
||||
|
||||
log.info("Creating a record");
|
||||
|
||||
let cryptoUri = "http://localhost:8080/crypto/steam";
|
||||
|
@ -128,10 +130,6 @@ function run_test() {
|
|||
bookmarkItem.encrypt();
|
||||
do_check_true(bookmarkItem.ciphertext != null);
|
||||
|
||||
_("Default key is " + CollectionKeys._default.keyStr);
|
||||
_("Bookmarks key is " + CollectionKeys.keyForCollection("bookmarks").keyStr);
|
||||
_("Bookmarks key is " + CollectionKeys._collections["bookmarks"].keyStr);
|
||||
|
||||
// Attempt to use the default key, because this is a collision that could
|
||||
// conceivably occur in the real world. Decryption will error, because
|
||||
// it's not the bookmarks key.
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
let atob = Cu.import("resource://services-sync/util.js").atob;
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
|
||||
/**
|
||||
* Testing the SHA256-HMAC key derivation process against test vectors
|
||||
* verified with the Firefox Home implementation.
|
||||
*/
|
||||
function run_test() {
|
||||
|
||||
// Test the production of keys from a sync key.
|
||||
let bundle = new SyncKeyBundle(PWDMGR_PASSPHRASE_REALM, "st3fan", "q7ynpwq7vsc9m34hankbyi3s3i");
|
||||
|
||||
// These should be compared to the results from Home, as they once were.
|
||||
let e = "14b8c09fa84e92729ee695160af6e0385f8f6215a25d14906e1747bdaa2de426";
|
||||
let h = "370e3566245d79fe602a3adb5137e42439cd2a571235197e0469d7d541b07875";
|
||||
|
||||
// The encryption key is stored as base64 for handing off to WeaveCrypto.
|
||||
let realE = Utils.bytesAsHex(atob(bundle.encryptionKey));
|
||||
let realH = Utils.bytesAsHex(bundle.hmacKey);
|
||||
|
||||
_("Real E: " + realE);
|
||||
_("Real H: " + realH);
|
||||
do_check_eq(realH, h);
|
||||
do_check_eq(realE, e);
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/ext/Observers.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
|
@ -146,6 +149,8 @@ function server_headers(metadata, response) {
|
|||
}
|
||||
|
||||
function run_test() {
|
||||
initTestLogging("Trace");
|
||||
|
||||
do_test_pending();
|
||||
|
||||
logger = Log4Moz.repository.getLogger('Test');
|
||||
|
@ -227,19 +232,7 @@ function run_test() {
|
|||
_("Test that the BasicAuthenticator doesn't screw up header case.");
|
||||
let res1 = new Resource("http://localhost:8080/foo");
|
||||
res1.setHeader("Authorization", "Basic foobar");
|
||||
res1.authenticator = new NoOpAuthenticator();
|
||||
do_check_eq(res1._headers["authorization"], "Basic foobar");
|
||||
do_check_eq(res1.headers["authorization"], "Basic foobar");
|
||||
let id = new Identity("secret", "guest", "guest");
|
||||
res1.authenticator = new BasicAuthenticator(id);
|
||||
|
||||
// In other words... it correctly overwrites our downcased version
|
||||
// when accessed through .headers.
|
||||
do_check_eq(res1._headers["authorization"], "Basic foobar");
|
||||
do_check_eq(res1.headers["authorization"], "Basic Z3Vlc3Q6Z3Vlc3Q=");
|
||||
do_check_eq(res1._headers["authorization"], "Basic Z3Vlc3Q6Z3Vlc3Q=");
|
||||
do_check_true(!res1._headers["Authorization"]);
|
||||
do_check_true(!res1.headers["Authorization"]);
|
||||
|
||||
_("GET a password protected resource (test that it'll fail w/o pass, no throw)");
|
||||
let res2 = new Resource("http://localhost:8080/protected");
|
||||
|
@ -249,8 +242,8 @@ function run_test() {
|
|||
do_check_false(content.success);
|
||||
|
||||
_("GET a password protected resource");
|
||||
let auth = new BasicAuthenticator(new Identity("secret", "guest", "guest"));
|
||||
let res3 = new Resource("http://localhost:8080/protected");
|
||||
let auth = Identity.getBasicResourceAuthenticator("guest", "guest");
|
||||
res3.authenticator = auth;
|
||||
do_check_eq(res3.authenticator, auth);
|
||||
content = res3.get();
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/ext/Observers.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
|
@ -261,19 +264,8 @@ add_test(function test_basicauth() {
|
|||
_("Test that the BasicAuthenticator doesn't screw up header case.");
|
||||
let res1 = new AsyncResource("http://localhost:8080/foo");
|
||||
res1.setHeader("Authorization", "Basic foobar");
|
||||
res1.authenticator = new NoOpAuthenticator();
|
||||
do_check_eq(res1._headers["authorization"], "Basic foobar");
|
||||
do_check_eq(res1.headers["authorization"], "Basic foobar");
|
||||
let id = new Identity("secret", "guest", "guest");
|
||||
res1.authenticator = new BasicAuthenticator(id);
|
||||
|
||||
// In other words... it correctly overwrites our downcased version
|
||||
// when accessed through .headers.
|
||||
do_check_eq(res1._headers["authorization"], "Basic foobar");
|
||||
do_check_eq(res1.headers["authorization"], "Basic Z3Vlc3Q6Z3Vlc3Q=");
|
||||
do_check_eq(res1._headers["authorization"], "Basic Z3Vlc3Q6Z3Vlc3Q=");
|
||||
do_check_true(!res1._headers["Authorization"]);
|
||||
do_check_true(!res1.headers["Authorization"]);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
@ -292,7 +284,7 @@ add_test(function test_get_protected_fail() {
|
|||
|
||||
add_test(function test_get_protected_success() {
|
||||
_("GET a password protected resource");
|
||||
let auth = new BasicAuthenticator(new Identity("secret", "guest", "guest"));
|
||||
let auth = Identity.getBasicResourceAuthenticator("guest", "guest");
|
||||
let res3 = new AsyncResource("http://localhost:8080/protected");
|
||||
res3.authenticator = auth;
|
||||
do_check_eq(res3.authenticator, auth);
|
||||
|
|
|
@ -25,10 +25,9 @@ function test_resource_user_agent() {
|
|||
"/1.1/johndoe/storage/meta/global": uaHandler(meta_global.handler()),
|
||||
});
|
||||
|
||||
setBasicCredentials("johndoe", "ilovejane");
|
||||
Weave.Service.serverURL = TEST_SERVER_URL;
|
||||
Weave.Service.clusterURL = TEST_CLUSTER_URL;
|
||||
Weave.Service.username = "johndoe";
|
||||
Weave.Service.password = "ilovejane";
|
||||
|
||||
let expectedUA = Services.appinfo.name + "/" + Services.appinfo.version +
|
||||
" FxSync/" + WEAVE_VERSION + "." +
|
||||
|
|
|
@ -43,12 +43,7 @@ function sync_httpd_setup() {
|
|||
}
|
||||
|
||||
function setUp() {
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "sekrit";
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
new FakeCryptoService();
|
||||
new SyncTestingInfrastructure("johndoe", "ilovejane", "sekrit");
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
|
|
|
@ -7,9 +7,7 @@ Cu.import("resource://services-sync/service.js");
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function run_test() {
|
||||
Service.account = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = Utils.generatePassphrase();
|
||||
setBasicCredentials("johndoe", "ilovejane", Utils.generatePassphrase());
|
||||
Service.serverURL = "http://weave.server/";
|
||||
|
||||
initTestLogging("Trace");
|
||||
|
@ -31,9 +29,9 @@ function make_sendCredentials_test(topic) {
|
|||
sendAndCompleteCalled = true;
|
||||
|
||||
// Verify it sends the correct data.
|
||||
do_check_eq(data.account, Service.account);
|
||||
do_check_eq(data.password, Service.password);
|
||||
do_check_eq(data.synckey, Service.passphrase);
|
||||
do_check_eq(data.account, Identity.account);
|
||||
do_check_eq(data.password, Identity.basicPassword);
|
||||
do_check_eq(data.synckey, Identity.syncKey);
|
||||
do_check_eq(data.serverURL, Service.serverURL);
|
||||
|
||||
this.controller.onComplete();
|
||||
|
|
|
@ -1,63 +1,12 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/service.js");
|
||||
Cu.import("resource://services-sync/status.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function test_identities() {
|
||||
_("Account related Service properties correspond to preference settings and update other object properties upon being set.");
|
||||
|
||||
try {
|
||||
_("Verify initial state");
|
||||
do_check_eq(Svc.Prefs.get("account"), undefined);
|
||||
do_check_eq(Svc.Prefs.get("username"), undefined);
|
||||
do_check_eq(ID.get("WeaveID").username, "");
|
||||
do_check_eq(ID.get("WeaveCryptoID").username, "");
|
||||
|
||||
_("The 'username' attribute is normalized to lower case, updates preferences and identities.");
|
||||
Service.username = "TarZan";
|
||||
do_check_eq(Service.username, "tarzan");
|
||||
do_check_eq(Svc.Prefs.get("username"), "tarzan");
|
||||
do_check_eq(ID.get("WeaveID").username, "tarzan");
|
||||
do_check_eq(ID.get("WeaveCryptoID").username, "tarzan");
|
||||
|
||||
_("If not set, the 'account attribute' falls back to the username for backwards compatibility.");
|
||||
do_check_eq(Service.account, "tarzan");
|
||||
|
||||
_("Setting 'username' to a non-truthy value resets the pref.");
|
||||
Service.username = null;
|
||||
do_check_eq(Service.username, "");
|
||||
do_check_eq(Service.account, "");
|
||||
const default_marker = {};
|
||||
do_check_eq(Svc.Prefs.get("username", default_marker), default_marker);
|
||||
do_check_eq(ID.get("WeaveID").username, null);
|
||||
do_check_eq(ID.get("WeaveCryptoID").username, null);
|
||||
|
||||
_("The 'account' attribute will set the 'username' if it doesn't contain characters that aren't allowed in the username.");
|
||||
Service.account = "johndoe";
|
||||
do_check_eq(Service.account, "johndoe");
|
||||
do_check_eq(Service.username, "johndoe");
|
||||
do_check_eq(Svc.Prefs.get("username"), "johndoe");
|
||||
do_check_eq(ID.get("WeaveID").username, "johndoe");
|
||||
do_check_eq(ID.get("WeaveCryptoID").username, "johndoe");
|
||||
|
||||
_("If 'account' contains disallowed characters such as @, 'username' will the base32 encoded SHA1 hash of 'account'");
|
||||
Service.account = "John@Doe.com";
|
||||
do_check_eq(Service.account, "john@doe.com");
|
||||
do_check_eq(Service.username, "7wohs32cngzuqt466q3ge7indszva4of");
|
||||
|
||||
_("Setting 'account' to a non-truthy value resets the pref.");
|
||||
Service.account = null;
|
||||
do_check_eq(Service.account, "");
|
||||
do_check_eq(Svc.Prefs.get("account", default_marker), default_marker);
|
||||
do_check_eq(Service.username, "");
|
||||
do_check_eq(Svc.Prefs.get("username", default_marker), default_marker);
|
||||
|
||||
} finally {
|
||||
Svc.Prefs.resetBranch("");
|
||||
}
|
||||
}
|
||||
|
||||
function test_urls() {
|
||||
_("URL related Service properties corresopnd to preference settings.");
|
||||
try {
|
||||
|
@ -69,7 +18,7 @@ function test_urls() {
|
|||
do_check_eq(Service.metaURL, undefined);
|
||||
|
||||
_("The 'clusterURL' attribute updates preferences and cached URLs.");
|
||||
Service.username = "johndoe";
|
||||
Identity.username = "johndoe";
|
||||
|
||||
// Since we don't have a cluster URL yet, these will still not be defined.
|
||||
do_check_eq(Service.infoURL, undefined);
|
||||
|
@ -106,10 +55,9 @@ function test_urls() {
|
|||
"http://weave.server/weave-password-reset");
|
||||
|
||||
_("Empty/false value for 'username' resets preference.");
|
||||
Service.username = "";
|
||||
Identity.username = "";
|
||||
do_check_eq(Svc.Prefs.get("username"), undefined);
|
||||
do_check_eq(ID.get("WeaveID").username, "");
|
||||
do_check_eq(ID.get("WeaveCryptoID").username, "");
|
||||
do_check_eq(Identity.username, null);
|
||||
|
||||
_("The 'serverURL' attributes updates/resets preferences.");
|
||||
// Identical value doesn't do anything
|
||||
|
@ -164,7 +112,6 @@ function test_locked() {
|
|||
}
|
||||
|
||||
function run_test() {
|
||||
test_identities();
|
||||
test_urls();
|
||||
test_syncID();
|
||||
test_locked();
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/main.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
|
@ -28,13 +32,12 @@ add_test(function test_change_password() {
|
|||
try {
|
||||
Weave.Service.serverURL = TEST_SERVER_URL;
|
||||
Weave.Service.clusterURL = TEST_CLUSTER_URL;
|
||||
Weave.Service.username = "johndoe";
|
||||
Weave.Service.password = "ilovejane";
|
||||
setBasicCredentials("johndoe", "ilovejane");
|
||||
|
||||
_("changePassword() returns false for a network error, the password won't change.");
|
||||
let res = Weave.Service.changePassword("ILoveJane83");
|
||||
do_check_false(res);
|
||||
do_check_eq(Weave.Service.password, "ilovejane");
|
||||
do_check_eq(Identity.basicPassword, "ilovejane");
|
||||
|
||||
_("Let's fire up the server and actually change the password.");
|
||||
server = httpd_setup({
|
||||
|
@ -44,28 +47,28 @@ add_test(function test_change_password() {
|
|||
|
||||
res = Weave.Service.changePassword("ILoveJane83");
|
||||
do_check_true(res);
|
||||
do_check_eq(Weave.Service.password, "ILoveJane83");
|
||||
do_check_eq(Identity.basicPassword, "ILoveJane83");
|
||||
do_check_eq(requestBody, "ILoveJane83");
|
||||
|
||||
_("Make sure the password has been persisted in the login manager.");
|
||||
let logins = Services.logins.findLogins({}, PWDMGR_HOST, null,
|
||||
PWDMGR_PASSWORD_REALM);
|
||||
do_check_eq(logins.length, 1);
|
||||
do_check_eq(logins[0].password, "ILoveJane83");
|
||||
|
||||
_("A non-ASCII password is UTF-8 encoded.");
|
||||
const moneyPassword = "moneyislike$£¥";
|
||||
res = Weave.Service.changePassword(moneyPassword);
|
||||
do_check_true(res);
|
||||
do_check_eq(Weave.Service.password, moneyPassword);
|
||||
do_check_eq(Identity.basicPassword, Utils.encodeUTF8(moneyPassword));
|
||||
do_check_eq(requestBody, Utils.encodeUTF8(moneyPassword));
|
||||
|
||||
_("changePassword() returns false for a server error, the password won't change.");
|
||||
Services.logins.removeAllLogins();
|
||||
Weave.Service.username = "janedoe";
|
||||
Weave.Service.password = "ilovejohn";
|
||||
setBasicCredentials("janedoe", "ilovejohn");
|
||||
res = Weave.Service.changePassword("ILoveJohn86");
|
||||
do_check_false(res);
|
||||
do_check_eq(Weave.Service.password, "ilovejohn");
|
||||
do_check_eq(Identity.basicPassword, "ilovejohn");
|
||||
|
||||
} finally {
|
||||
Weave.Svc.Prefs.resetBranch("");
|
||||
|
|
|
@ -16,7 +16,7 @@ function test_findCluster() {
|
|||
let server;
|
||||
try {
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.username = "johndoe";
|
||||
Identity.account = "johndoe";
|
||||
|
||||
_("_findCluster() throws on network errors (e.g. connection refused).");
|
||||
do_check_throws(function() {
|
||||
|
@ -36,23 +36,23 @@ function test_findCluster() {
|
|||
do_check_eq(cluster, "http://weave.user.node/");
|
||||
|
||||
_("A 'null' response is converted to null.");
|
||||
Service.username = "jimdoe";
|
||||
Identity.account = "jimdoe";
|
||||
cluster = Service._findCluster();
|
||||
do_check_eq(cluster, null);
|
||||
|
||||
_("If a 404 is encountered, the server URL is taken as the cluster URL");
|
||||
Service.username = "janedoe";
|
||||
Identity.account = "janedoe";
|
||||
cluster = Service._findCluster();
|
||||
do_check_eq(cluster, Service.serverURL);
|
||||
|
||||
_("A 400 response will throw an error.");
|
||||
Service.username = "juliadoe";
|
||||
Identity.account = "juliadoe";
|
||||
do_check_throws(function() {
|
||||
Service._findCluster();
|
||||
});
|
||||
|
||||
_("Any other server response (e.g. 500) will throw an error.");
|
||||
Service.username = "joedoe";
|
||||
Identity.account = "joedoe";
|
||||
do_check_throws(function() {
|
||||
Service._findCluster();
|
||||
});
|
||||
|
@ -74,7 +74,7 @@ function test_setCluster() {
|
|||
});
|
||||
try {
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.username = "johndoe";
|
||||
Identity.account = "johndoe";
|
||||
|
||||
_("Check initial state.");
|
||||
do_check_eq(Service.clusterURL, "");
|
||||
|
@ -88,7 +88,7 @@ function test_setCluster() {
|
|||
do_check_eq(Service.clusterURL, "http://weave.user.node/");
|
||||
|
||||
_("A 'null' response won't make a difference either.");
|
||||
Service.username = "jimdoe";
|
||||
Identity.account = "jimdoe";
|
||||
do_check_false(Service._setCluster());
|
||||
do_check_eq(Service.clusterURL, "http://weave.user.node/");
|
||||
|
||||
|
@ -106,7 +106,7 @@ function test_updateCluster() {
|
|||
});
|
||||
try {
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.username = "johndoe";
|
||||
Identity.account = "johndoe";
|
||||
|
||||
_("Check initial state.");
|
||||
do_check_eq(Service.clusterURL, "");
|
||||
|
@ -125,7 +125,7 @@ function test_updateCluster() {
|
|||
do_check_eq(parseFloat(Svc.Prefs.get("lastClusterUpdate")), lastUpdate);
|
||||
|
||||
_("Time travel 30 mins into the past and the update will work.");
|
||||
Service.username = "janedoe";
|
||||
Identity.account = "janedoe";
|
||||
Svc.Prefs.set("lastClusterUpdate", (lastUpdate - 30*60*1000).toString());
|
||||
|
||||
before = Date.now();
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/main.js");
|
||||
Cu.import("resource://services-sync/service.js");
|
||||
Cu.import("resource://services-sync/engines.js");
|
||||
|
@ -5,6 +8,7 @@ Cu.import("resource://services-sync/util.js");
|
|||
Cu.import("resource://services-sync/status.js");
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
Cu.import("resource://services-sync/keys.js");
|
||||
Cu.import("resource://services-sync/engines/tabs.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
|
||||
|
@ -122,7 +126,7 @@ add_test(function v4_upgrade() {
|
|||
serverResp = serverKeys.fetch(Weave.Service.cryptoKeysURL).response;
|
||||
do_check_true(serverResp.success);
|
||||
|
||||
serverDecrypted = serverKeys.decrypt(Weave.Service.syncKeyBundle);
|
||||
serverDecrypted = serverKeys.decrypt(Weave.Identity.syncKeyBundle);
|
||||
_("Retrieved WBO: " + JSON.stringify(serverDecrypted));
|
||||
_("serverKeys: " + JSON.stringify(serverKeys));
|
||||
|
||||
|
@ -131,7 +135,7 @@ add_test(function v4_upgrade() {
|
|||
|
||||
function retrieve_and_compare_default(should_succeed) {
|
||||
let serverDefault = retrieve_server_default();
|
||||
let localDefault = CollectionKeys.keyForCollection().keyPair;
|
||||
let localDefault = CollectionKeys.keyForCollection().keyPairB64;
|
||||
|
||||
_("Retrieved keyBundle: " + JSON.stringify(serverDefault));
|
||||
_("Local keyBundle: " + JSON.stringify(localDefault));
|
||||
|
@ -146,7 +150,7 @@ add_test(function v4_upgrade() {
|
|||
function set_server_keys(pair) {
|
||||
serverDecrypted.default = pair;
|
||||
serverKeys.cleartext = serverDecrypted;
|
||||
serverKeys.encrypt(Weave.Service.syncKeyBundle);
|
||||
serverKeys.encrypt(Weave.Identity.syncKeyBundle);
|
||||
serverKeys.upload(Weave.Service.cryptoKeysURL);
|
||||
}
|
||||
|
||||
|
@ -235,18 +239,12 @@ add_test(function v5_upgrade() {
|
|||
|
||||
Status.resetSync();
|
||||
|
||||
Weave.Service.username = "johndoe";
|
||||
Weave.Service.password = "ilovejane";
|
||||
Weave.Service.passphrase = passphrase;
|
||||
|
||||
setBasicCredentials("johndoe", "ilovejane", passphrase);
|
||||
Weave.Service.serverURL = TEST_SERVER_URL;
|
||||
Weave.Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
//
|
||||
// Test an upgrade where the contents of the server would cause us to error
|
||||
// -- keys decrypted with a different sync key, for example.
|
||||
//
|
||||
|
||||
_("Testing v4 -> v5 (or similar) upgrade.");
|
||||
function update_server_keys(syncKeyBundle, wboName, collWBO) {
|
||||
generateNewKeys();
|
||||
|
@ -265,12 +263,11 @@ add_test(function v5_upgrade() {
|
|||
_("New meta/global: " + JSON.stringify(meta_global));
|
||||
|
||||
// Fill the keys with bad data.
|
||||
let badKeys = new SyncKeyBundle(null, null, "aaaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
badKeys.generateEntry();
|
||||
let badKeys = new SyncKeyBundle("foobar", "aaaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||
update_server_keys(badKeys, "keys", "crypto/keys"); // v4
|
||||
update_server_keys(badKeys, "bulk", "crypto/bulk"); // v5
|
||||
|
||||
// ... and get new ones.
|
||||
_("Generating new keys.");
|
||||
generateNewKeys();
|
||||
|
||||
// Now sync and see what happens. It should be a version fail, not a crypto
|
||||
|
|
|
@ -11,8 +11,7 @@ let collections = {steam: 65.11328,
|
|||
diesel: 2.25488281};
|
||||
|
||||
function run_test() {
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
setBasicCredentials("johndoe", "ilovejane");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
|
@ -32,8 +31,9 @@ add_test(function test_success() {
|
|||
do_check_true(Utils.deepEquals(info, collections));
|
||||
|
||||
// Ensure that the request is sent off with the right bits.
|
||||
do_check_true(basic_auth_matches(handler.request, Service.username,
|
||||
Service.password));
|
||||
do_check_true(basic_auth_matches(handler.request,
|
||||
Identity.username,
|
||||
Identity.basicPassword));
|
||||
let expectedUA = Services.appinfo.name + "/" + Services.appinfo.version +
|
||||
" FxSync/" + WEAVE_VERSION + "." +
|
||||
Services.appinfo.appBuildID + ".desktop";
|
||||
|
|
|
@ -79,15 +79,15 @@ add_test(function test_login_logout() {
|
|||
do_check_false(Service.isLoggedIn);
|
||||
|
||||
_("Try again with username and password set.");
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Identity.account = "johndoe";
|
||||
Identity.basicPassword = "ilovejane";
|
||||
Service.login();
|
||||
do_check_eq(Status.service, CLIENT_NOT_CONFIGURED);
|
||||
do_check_eq(Status.login, LOGIN_FAILED_NO_PASSPHRASE);
|
||||
do_check_false(Service.isLoggedIn);
|
||||
|
||||
_("Success if passphrase is set.");
|
||||
Service.passphrase = "foo";
|
||||
Identity.syncKey = "foo";
|
||||
Service.login();
|
||||
do_check_eq(Status.service, STATUS_OK);
|
||||
do_check_eq(Status.login, LOGIN_SUCCEEDED);
|
||||
|
@ -95,9 +95,7 @@ add_test(function test_login_logout() {
|
|||
|
||||
_("We can also pass username, password and passphrase to login().");
|
||||
Service.login("janedoe", "incorrectpassword", "bar");
|
||||
do_check_eq(Service.username, "janedoe");
|
||||
do_check_eq(Service.password, "incorrectpassword");
|
||||
do_check_eq(Service.passphrase, "bar");
|
||||
setBasicCredentials("janedoe", "incorrectpassword", "bar");
|
||||
do_check_eq(Status.service, LOGIN_FAILED);
|
||||
do_check_eq(Status.login, LOGIN_FAILED_LOGIN_REJECTED);
|
||||
do_check_false(Service.isLoggedIn);
|
||||
|
@ -113,9 +111,7 @@ add_test(function test_login_logout() {
|
|||
Svc.Obs.add("weave:service:setup-complete", function() {
|
||||
notified = true;
|
||||
});
|
||||
Service.username = "";
|
||||
Service.password = "";
|
||||
Service.passphrase = "";
|
||||
setBasicCredentials(null, null, null);
|
||||
Service.login("janedoe", "ilovejohn", "bar");
|
||||
do_check_true(notified);
|
||||
do_check_eq(Status.service, STATUS_OK);
|
||||
|
@ -138,9 +134,7 @@ add_test(function test_login_logout() {
|
|||
|
||||
add_test(function test_login_on_sync() {
|
||||
let server = setup();
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "bar";
|
||||
setBasicCredentials("johndoe", "ilovejane", "bar");
|
||||
|
||||
try {
|
||||
_("Sync calls login.");
|
||||
|
@ -202,10 +196,11 @@ add_test(function test_login_on_sync() {
|
|||
mpLocked = true;
|
||||
|
||||
// Testing exception handling if master password dialog is canceled.
|
||||
// Do this by stubbing out Service.passphrase.
|
||||
let oldPP = Service.__lookupGetter__("passphrase");
|
||||
_("Old passphrase function is " + oldPP);
|
||||
Service.__defineGetter__("passphrase",
|
||||
// Do this by monkeypatching.
|
||||
let oldGetter = Identity.__lookupGetter__("syncKey");
|
||||
let oldSetter = Identity.__lookupSetter__("syncKey");
|
||||
_("Old passphrase function is " + oldGetter);
|
||||
Identity.__defineGetter__("syncKey",
|
||||
function() {
|
||||
throw "User canceled Master Password entry";
|
||||
});
|
||||
|
@ -233,6 +228,9 @@ add_test(function test_login_on_sync() {
|
|||
do_check_true(cSTCalled);
|
||||
do_check_false(lockedSyncCalled);
|
||||
|
||||
Identity.__defineGetter__("syncKey", oldGetter);
|
||||
Identity.__defineSetter__("syncKey", oldSetter);
|
||||
|
||||
// N.B., a bunch of methods are stubbed at this point. Be careful putting
|
||||
// new tests after this point!
|
||||
|
||||
|
|
|
@ -62,9 +62,7 @@ function run_test() {
|
|||
"/user/1.0/johndoe/password": change_password
|
||||
});
|
||||
|
||||
Service.username = "johndoe";
|
||||
Service.password = JAPANESE;
|
||||
Service.passphrase = "cantentsveryrelevantabbbb";
|
||||
setBasicCredentials("johndoe", JAPANESE, "irrelevant");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
|
||||
try {
|
||||
|
@ -73,13 +71,14 @@ function run_test() {
|
|||
do_check_false(Service.verifyLogin());
|
||||
do_check_eq(server_password, "foobar");
|
||||
|
||||
_("Make the server password the low byte version of our password. Login should work and have transparently changed the password to the UTF8 version.");
|
||||
_("Make the server password the low byte version of our password.");
|
||||
server_password = LOWBYTES;
|
||||
do_check_true(Service.verifyLogin());
|
||||
do_check_eq(server_password, Utils.encodeUTF8(JAPANESE));
|
||||
do_check_false(Service.verifyLogin());
|
||||
do_check_eq(server_password, LOWBYTES);
|
||||
|
||||
_("Can't use a password that has the same low bytes as ours.");
|
||||
Service.password = APPLES;
|
||||
server_password = Utils.encodeUTF8(JAPANESE);
|
||||
Identity.basicPassword = APPLES;
|
||||
do_check_false(Service.verifyLogin());
|
||||
do_check_eq(server_password, Utils.encodeUTF8(JAPANESE));
|
||||
|
||||
|
|
|
@ -7,9 +7,7 @@ function run_test() {
|
|||
// Ensure we have a blank slate to start.
|
||||
Services.logins.removeAllLogins();
|
||||
|
||||
Weave.Service.username = "johndoe";
|
||||
Weave.Service.password = "ilovejane";
|
||||
Weave.Service.passphrase = "abbbbbcccccdddddeeeeefffff";
|
||||
setBasicCredentials("johndoe", "ilovejane", "abbbbbcccccdddddeeeeefffff");
|
||||
|
||||
_("Confirm initial environment is empty.");
|
||||
let logins = Services.logins.findLogins({}, PWDMGR_HOST, null,
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/engines.js");
|
||||
Cu.import("resource://services-sync/service.js");
|
||||
Cu.import("resource://services-sync/status.js");
|
||||
|
@ -27,9 +30,8 @@ function run_test() {
|
|||
|
||||
add_test(function test_resetLocalData() {
|
||||
// Set up.
|
||||
Service.username = "foobar";
|
||||
Service.password = "blablabla";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("foobar", "blablabla", // Law Blog
|
||||
"abcdeabcdeabcdeabcdeabcdea");
|
||||
Status.enforceBackoff = true;
|
||||
Status.backoffInterval = 42;
|
||||
Status.minimumNextSync = 23;
|
||||
|
@ -52,8 +54,8 @@ add_test(function test_resetLocalData() {
|
|||
|
||||
// Verify the site was nuked from orbit.
|
||||
do_check_eq(Svc.Prefs.get("username"), undefined);
|
||||
do_check_eq(Service.password, "");
|
||||
do_check_eq(Service.passphrase, "");
|
||||
do_check_eq(Identity.basicPassword, null);
|
||||
do_check_eq(Identity.syncKey, null);
|
||||
|
||||
do_check_eq(Status.service, CLIENT_NOT_CONFIGURED);
|
||||
do_check_false(Status.enforceBackoff);
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/ext/Observers.js");
|
||||
Cu.import("resource://services-sync/status.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
|
@ -7,9 +10,11 @@ Cu.import("resource://services-sync/engines.js");
|
|||
function run_test() {
|
||||
_("When imported, Service.onStartup is called");
|
||||
|
||||
// Test fixtures
|
||||
Svc.Prefs.set("registerEngines", "Tab,Bookmarks,Form,History");
|
||||
Svc.Prefs.set("username", "johndoe");
|
||||
new SyncTestingInfrastructure();
|
||||
|
||||
// Test fixtures
|
||||
Identity.username = "johndoe";
|
||||
|
||||
Cu.import("resource://services-sync/service.js");
|
||||
|
||||
|
@ -21,10 +26,6 @@ function run_test() {
|
|||
do_check_true(Utils.deepEquals([engine.name for each (engine in engines)],
|
||||
['tabs', 'bookmarks', 'forms', 'history']));
|
||||
|
||||
_("Identities are registered.");
|
||||
do_check_eq(ID.get('WeaveID').username, "johndoe");
|
||||
do_check_eq(ID.get('WeaveCryptoID').username, "johndoe");
|
||||
|
||||
_("Observers are notified of startup");
|
||||
do_test_pending();
|
||||
do_check_false(Status.ready);
|
||||
|
|
|
@ -32,11 +32,7 @@ function run_test() {
|
|||
|
||||
try {
|
||||
_("Set up test fixtures.");
|
||||
Weave.Service.serverURL = TEST_SERVER_URL;
|
||||
Weave.Service.clusterURL = TEST_CLUSTER_URL;
|
||||
Weave.Service.username = "johndoe";
|
||||
Weave.Service.password = "ilovejane";
|
||||
Weave.Service.passphrase = "foo";
|
||||
new SyncTestingInfrastructure("johndoe", "ilovejane", "foo");
|
||||
SyncScheduler.globalScore = GLOBAL_SCORE;
|
||||
// Avoid daily ping
|
||||
Weave.Svc.Prefs.set("lastPing", Math.floor(Date.now() / 1000));
|
||||
|
@ -52,7 +48,7 @@ function run_test() {
|
|||
do_check_eq(Weave.Status.login, Weave.LOGIN_SUCCEEDED);
|
||||
|
||||
_("Simulate having changed the password somewhere else.");
|
||||
Weave.Service.password = "ilovejosephine";
|
||||
Identity.basicPassword = "ilovejosephine";
|
||||
|
||||
_("Let's try to sync.");
|
||||
Weave.Service.sync();
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/main.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://services-sync/status.js");
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/record.js");
|
||||
Cu.import("resource://services-sync/keys.js");
|
||||
Cu.import("resource://services-sync/log4moz.js");
|
||||
|
||||
function run_test() {
|
||||
|
@ -67,14 +70,14 @@ function run_test() {
|
|||
_("Checking Status.sync with no credentials.");
|
||||
Weave.Service.verifyAndFetchSymmetricKeys();
|
||||
do_check_eq(Status.sync, CREDENTIALS_CHANGED);
|
||||
do_check_eq(Status.login, LOGIN_FAILED_INVALID_PASSPHRASE);
|
||||
do_check_eq(Status.login, LOGIN_FAILED_NO_PASSPHRASE);
|
||||
|
||||
_("Log in with an old secret phrase, is upgraded to Sync Key.");
|
||||
Weave.Service.login("johndoe", "ilovejane", "my old secret phrase!!1!");
|
||||
_("End of login");
|
||||
do_check_true(Weave.Service.isLoggedIn);
|
||||
do_check_true(Utils.isPassphrase(Weave.Service.passphrase));
|
||||
do_check_true(Utils.isPassphrase(Weave.Service.syncKeyBundle.keyStr));
|
||||
let syncKey = Weave.Service.passphrase;
|
||||
do_check_true(Utils.isPassphrase(Identity.syncKey));
|
||||
let syncKey = Identity.syncKey;
|
||||
Weave.Service.startOver();
|
||||
|
||||
Weave.Service.serverURL = TEST_SERVER_URL;
|
||||
|
@ -120,12 +123,12 @@ function run_test() {
|
|||
do_check_eq(metaModified, meta_global.modified);
|
||||
|
||||
_("Checking bad passphrases.");
|
||||
let pp = Weave.Service.passphrase;
|
||||
Weave.Service.passphrase = "notvalid";
|
||||
let pp = Identity.syncKey;
|
||||
Identity.syncKey = "notvalid";
|
||||
do_check_false(Weave.Service.verifyAndFetchSymmetricKeys());
|
||||
do_check_eq(Status.sync, CREDENTIALS_CHANGED);
|
||||
do_check_eq(Status.login, LOGIN_FAILED_INVALID_PASSPHRASE);
|
||||
Weave.Service.passphrase = pp;
|
||||
Identity.syncKey = pp;
|
||||
do_check_true(Weave.Service.verifyAndFetchSymmetricKeys());
|
||||
|
||||
// changePassphrase wipes our keys, and they're regenerated on next sync.
|
||||
|
@ -149,7 +152,7 @@ function run_test() {
|
|||
// server, just as might happen with a second client.
|
||||
_("Attempting to screw up HMAC by re-encrypting keys.");
|
||||
let keys = CollectionKeys.asWBO();
|
||||
let b = new BulkKeyBundle("hmacerror", "hmacerror");
|
||||
let b = new BulkKeyBundle("hmacerror");
|
||||
b.generateRandom();
|
||||
collections.crypto = keys.modified = 100 + (Date.now()/1000); // Future modification time.
|
||||
keys.encrypt(b);
|
||||
|
|
|
@ -66,19 +66,13 @@ function sync_httpd_setup(handlers) {
|
|||
}
|
||||
|
||||
function setUp() {
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
// So that we can poke at meta/global.
|
||||
new FakeCryptoService();
|
||||
|
||||
new SyncTestingInfrastructure("johndoe", "ilovejane",
|
||||
"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");
|
||||
serverKeys.encrypt(Service.syncKeyBundle);
|
||||
serverKeys.encrypt(Identity.syncKeyBundle);
|
||||
return serverKeys.upload(Service.cryptoKeysURL).success;
|
||||
}
|
||||
|
||||
|
@ -260,7 +254,7 @@ add_test(function test_enabledRemotely() {
|
|||
try {
|
||||
_("Upload some keys to avoid a fresh start.");
|
||||
let wbo = CollectionKeys.generateNewKeysWBO();
|
||||
wbo.encrypt(Service.syncKeyBundle);
|
||||
wbo.encrypt(Identity.syncKeyBundle);
|
||||
do_check_eq(200, wbo.upload(Service.cryptoKeysURL).status);
|
||||
|
||||
_("Engine is disabled.");
|
||||
|
|
|
@ -58,8 +58,7 @@ function run_test() {
|
|||
|
||||
_("Try again with username and password set.");
|
||||
Status.resetSync();
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
setBasicCredentials("johndoe", "ilovejane", null);
|
||||
do_check_false(Service.verifyLogin());
|
||||
do_check_eq(Status.service, CLIENT_NOT_CONFIGURED);
|
||||
do_check_eq(Status.login, LOGIN_FAILED_NO_PASSPHRASE);
|
||||
|
@ -69,14 +68,15 @@ function run_test() {
|
|||
|
||||
_("Success if passphrase is set.");
|
||||
Status.resetSync();
|
||||
Service.passphrase = "foo";
|
||||
Identity.syncKey = "foo";
|
||||
do_check_true(Service.verifyLogin());
|
||||
do_check_eq(Status.service, STATUS_OK);
|
||||
do_check_eq(Status.login, LOGIN_SUCCEEDED);
|
||||
|
||||
_("If verifyLogin() encounters a server error, it flips on the backoff flag and notifies observers on a 503 with Retry-After.");
|
||||
Status.resetSync();
|
||||
Service.username = "janedoe";
|
||||
Identity.account = "janedoe";
|
||||
Service._updateCachedURLs();
|
||||
do_check_false(Status.enforceBackoff);
|
||||
let backoffInterval;
|
||||
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
|
||||
|
|
|
@ -31,8 +31,8 @@ function setUpTestFixtures() {
|
|||
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
Service.username = "johndoe";
|
||||
Service.passphrase = "aabcdeabcdeabcdeabcdeabcde";
|
||||
|
||||
setBasicCredentials("johndoe", null, "aabcdeabcdeabcdeabcdeabcde");
|
||||
}
|
||||
|
||||
|
||||
|
@ -55,6 +55,7 @@ add_test(function test_wipeServer_list_success() {
|
|||
|
||||
try {
|
||||
setUpTestFixtures();
|
||||
new SyncTestingInfrastructure("johndoe", "irrelevant", "irrelevant");
|
||||
|
||||
_("Confirm initial environment.");
|
||||
do_check_false(steam_coll.deleted);
|
||||
|
@ -88,6 +89,7 @@ add_test(function test_wipeServer_list_503() {
|
|||
|
||||
try {
|
||||
setUpTestFixtures();
|
||||
new SyncTestingInfrastructure("johndoe", "irrelevant", "irrelevant");
|
||||
|
||||
_("Confirm initial environment.");
|
||||
do_check_false(steam_coll.deleted);
|
||||
|
@ -135,6 +137,7 @@ add_test(function test_wipeServer_all_success() {
|
|||
setUpTestFixtures();
|
||||
|
||||
_("Try deletion.");
|
||||
new SyncTestingInfrastructure("johndoe", "irrelevant", "irrelevant");
|
||||
let returnedTimestamp = Service.wipeServer();
|
||||
do_check_true(deleted);
|
||||
do_check_eq(returnedTimestamp, serverTimestamp);
|
||||
|
@ -166,6 +169,7 @@ add_test(function test_wipeServer_all_404() {
|
|||
setUpTestFixtures();
|
||||
|
||||
_("Try deletion.");
|
||||
new SyncTestingInfrastructure("johndoe", "irrelevant", "irrelevant");
|
||||
let returnedTimestamp = Service.wipeServer();
|
||||
do_check_true(deleted);
|
||||
do_check_eq(returnedTimestamp, serverTimestamp);
|
||||
|
@ -194,6 +198,7 @@ add_test(function test_wipeServer_all_503() {
|
|||
_("Try deletion.");
|
||||
let error;
|
||||
try {
|
||||
new SyncTestingInfrastructure("johndoe", "irrelevant", "irrelevant");
|
||||
Service.wipeServer();
|
||||
do_throw("Should have thrown!");
|
||||
} catch (ex) {
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/status.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function run_test() {
|
||||
initTestLogging("Trace");
|
||||
|
||||
try {
|
||||
_("Verify initial setup.");
|
||||
do_check_eq(ID.get("WeaveID"), null);
|
||||
do_check_eq(ID.get("WeaveCryptoID"), null);
|
||||
_("Ensure fresh config.");
|
||||
Identity.deleteSyncCredentials();
|
||||
|
||||
_("Fresh setup, we're not configured.");
|
||||
do_check_eq(Status.checkSetup(), CLIENT_NOT_CONFIGURED);
|
||||
|
@ -15,27 +19,22 @@ function run_test() {
|
|||
Status.resetSync();
|
||||
|
||||
_("Let's provide a username.");
|
||||
Svc.Prefs.set("username", "johndoe");
|
||||
Identity.username = "johndoe";
|
||||
do_check_eq(Status.checkSetup(), CLIENT_NOT_CONFIGURED);
|
||||
do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
|
||||
Status.resetSync();
|
||||
|
||||
_("checkSetup() created a WeaveID identity.");
|
||||
let id = ID.get("WeaveID");
|
||||
do_check_true(!!id);
|
||||
do_check_neq(Identity.username, null);
|
||||
|
||||
_("Let's provide a password.");
|
||||
id.password = "carotsalad";
|
||||
Identity.basicPassword = "carotsalad";
|
||||
do_check_eq(Status.checkSetup(), CLIENT_NOT_CONFIGURED);
|
||||
do_check_eq(Status.login, LOGIN_FAILED_NO_PASSPHRASE);
|
||||
Status.resetSync();
|
||||
|
||||
_("checkSetup() created a WeaveCryptoID identity");
|
||||
id = ID.get("WeaveCryptoID");
|
||||
do_check_true(!!id);
|
||||
|
||||
_("Let's provide a passphrase");
|
||||
id.keyStr = "a-bcdef-abcde-acbde-acbde-acbde";
|
||||
Identity.syncKey = "a-bcdef-abcde-acbde-acbde-acbde";
|
||||
_("checkSetup()");
|
||||
do_check_eq(Status.checkSetup(), STATUS_OK);
|
||||
Status.resetSync();
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ function test_toFetch() {
|
|||
do_check_eq(engine.toFetch[0], toFetch[0]);
|
||||
do_check_eq(engine.toFetch[1], toFetch[1]);
|
||||
} finally {
|
||||
syncTesting = new SyncTestingInfrastructure(makeSteamEngine);
|
||||
Svc.Prefs.resetBranch("");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ function test_previousFailed() {
|
|||
do_check_eq(engine.previousFailed[0], previousFailed[0]);
|
||||
do_check_eq(engine.previousFailed[1], previousFailed[1]);
|
||||
} finally {
|
||||
syncTesting = new SyncTestingInfrastructure(makeSteamEngine);
|
||||
Svc.Prefs.resetBranch("");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,6 @@ function test_resetClient() {
|
|||
do_check_eq(engine.toFetch.length, 0);
|
||||
do_check_eq(engine.previousFailed.length, 0);
|
||||
} finally {
|
||||
syncTesting = new SyncTestingInfrastructure(makeSteamEngine);
|
||||
Svc.Prefs.resetBranch("");
|
||||
}
|
||||
}
|
||||
|
@ -182,7 +181,6 @@ function test_wipeServer() {
|
|||
|
||||
} finally {
|
||||
server.stop(do_test_finished);
|
||||
syncTesting = new SyncTestingInfrastructure(makeSteamEngine);
|
||||
Svc.Prefs.resetBranch("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,13 @@ function cleanAndGo(server) {
|
|||
server.stop(run_next_test);
|
||||
}
|
||||
|
||||
function configureService(username, password) {
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
Identity.account = username || "foo";
|
||||
Identity.basicPassword = password || "password";
|
||||
}
|
||||
|
||||
function createServerAndConfigureClient() {
|
||||
let engine = new RotaryEngine();
|
||||
|
||||
|
|
|
@ -49,14 +49,12 @@ function sync_httpd_setup() {
|
|||
}
|
||||
|
||||
function setUp() {
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("johndoe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
|
||||
generateNewKeys();
|
||||
let serverKeys = CollectionKeys.asWBO("crypto", "keys");
|
||||
serverKeys.encrypt(Service.syncKeyBundle);
|
||||
serverKeys.encrypt(Identity.syncKeyBundle);
|
||||
return serverKeys.upload(Service.cryptoKeysURL).success;
|
||||
}
|
||||
|
||||
|
@ -213,14 +211,16 @@ add_test(function test_calculateBackoff() {
|
|||
// Test no interval larger than the maximum backoff is used if
|
||||
// Status.backoffInterval is smaller.
|
||||
Status.backoffInterval = 5;
|
||||
let backoffInterval = Utils.calculateBackoff(50, MAXIMUM_BACKOFF_INTERVAL);
|
||||
let backoffInterval = Utils.calculateBackoff(50, MAXIMUM_BACKOFF_INTERVAL,
|
||||
Status.backoffInterval);
|
||||
|
||||
do_check_eq(backoffInterval, MAXIMUM_BACKOFF_INTERVAL);
|
||||
|
||||
// Test Status.backoffInterval is used if it is
|
||||
// larger than MAXIMUM_BACKOFF_INTERVAL.
|
||||
Status.backoffInterval = MAXIMUM_BACKOFF_INTERVAL + 10;
|
||||
backoffInterval = Utils.calculateBackoff(50, MAXIMUM_BACKOFF_INTERVAL);
|
||||
backoffInterval = Utils.calculateBackoff(50, MAXIMUM_BACKOFF_INTERVAL,
|
||||
Status.backoffInterval);
|
||||
|
||||
do_check_eq(backoffInterval, MAXIMUM_BACKOFF_INTERVAL + 10);
|
||||
|
||||
|
@ -466,9 +466,7 @@ add_test(function test_autoconnect_nextSync_future() {
|
|||
cleanUpAndGo();
|
||||
});
|
||||
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
setBasicCredentials("johndoe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
SyncScheduler.delayedAutoConnect(0);
|
||||
});
|
||||
|
||||
|
@ -480,9 +478,10 @@ add_test(function test_autoconnect_mp_locked() {
|
|||
let origLocked = Utils.mpLocked;
|
||||
Utils.mpLocked = function() true;
|
||||
|
||||
let origPP = Service.__lookupGetter__("passphrase");
|
||||
delete Service.passphrase;
|
||||
Service.__defineGetter__("passphrase", function() {
|
||||
let origGetter = Identity.__lookupGetter__("syncKey");
|
||||
let origSetter = Identity.__lookupSetter__("syncKey");
|
||||
delete Identity.syncKey;
|
||||
Identity.__defineGetter__("syncKey", function() {
|
||||
_("Faking Master Password entry cancelation.");
|
||||
throw "User canceled Master Password entry";
|
||||
});
|
||||
|
@ -495,8 +494,9 @@ add_test(function test_autoconnect_mp_locked() {
|
|||
do_check_eq(Status.login, MASTER_PASSWORD_LOCKED);
|
||||
|
||||
Utils.mpLocked = origLocked;
|
||||
delete Service.passphrase;
|
||||
Service.__defineGetter__("passphrase", origPP);
|
||||
delete Identity.syncKey;
|
||||
Identity.__defineGetter__("syncKey", origGetter);
|
||||
Identity.__defineSetter__("syncKey", origSetter);
|
||||
|
||||
cleanUpAndGo(server);
|
||||
});
|
||||
|
@ -849,10 +849,8 @@ add_test(function test_sync_503_Retry_After() {
|
|||
|
||||
add_test(function test_loginError_recoverable_reschedules() {
|
||||
_("Verify that a recoverable login error schedules a new sync.");
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
setBasicCredentials("johndoe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
Service.persistLogin();
|
||||
Status.resetSync(); // reset Status.login
|
||||
|
@ -893,10 +891,8 @@ add_test(function test_loginError_recoverable_reschedules() {
|
|||
|
||||
add_test(function test_loginError_fatal_clearsTriggers() {
|
||||
_("Verify that a fatal login error clears sync triggers.");
|
||||
Service.username = "johndoe";
|
||||
Service.password = "ilovejane";
|
||||
Service.passphrase = "abcdeabcdeabcdeabcdeabcdea";
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
setBasicCredentials("johndoe", "ilovejane", "abcdeabcdeabcdeabcdeabcdea");
|
||||
Service.serverURL = TEST_SERVER_URL;
|
||||
Service.clusterURL = TEST_CLUSTER_URL;
|
||||
Service.persistLogin();
|
||||
Status.resetSync(); // reset Status.login
|
||||
|
|
|
@ -57,9 +57,7 @@ add_test(function test_auth() {
|
|||
let handler = httpd_handler(200, "OK");
|
||||
let server = httpd_setup({"/resource": handler});
|
||||
|
||||
let id = new Identity(PWDMGR_PASSWORD_REALM, "johndoe");
|
||||
id.password = "ilovejane";
|
||||
ID.set("WeaveID", id);
|
||||
setBasicCredentials("johndoe", "ilovejane", "XXXXXXXXX");
|
||||
|
||||
let request = new SyncStorageRequest(STORAGE_REQUEST_RESOURCE_URL);
|
||||
request.get(function (error) {
|
||||
|
@ -67,7 +65,8 @@ add_test(function test_auth() {
|
|||
do_check_eq(this.response.status, 200);
|
||||
do_check_true(basic_auth_matches(handler.request, "johndoe", "ilovejane"));
|
||||
|
||||
ID.del("WeaveID");
|
||||
Svc.Prefs.reset("");
|
||||
|
||||
server.stop(run_next_test);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/main.js");
|
||||
var btoa = Cu.import("resource://services-sync/util.js").btoa;
|
||||
|
||||
|
@ -21,11 +25,12 @@ function run_test() {
|
|||
do_check_eq(normalized, "abcdeabcdeabcdeabcde");
|
||||
|
||||
// Now run through the upgrade.
|
||||
Identity.account = "johndoe";
|
||||
Weave.Service.syncID = "1234567890";
|
||||
Weave.Service.passphrase = normalized; // UI normalizes.
|
||||
do_check_false(Utils.isPassphrase(Weave.Service.passphrase));
|
||||
Identity.syncKey = normalized; // UI normalizes.
|
||||
do_check_false(Utils.isPassphrase(Identity.syncKey));
|
||||
Weave.Service.upgradeSyncKey(Weave.Service.syncID);
|
||||
let upgraded = Weave.Service.passphrase;
|
||||
let upgraded = Identity.syncKey;
|
||||
_("Upgraded: " + upgraded);
|
||||
do_check_true(Utils.isPassphrase(upgraded));
|
||||
|
||||
|
|
|
@ -4,107 +4,14 @@ tail =
|
|||
|
||||
[test_load_modules.js]
|
||||
|
||||
[test_Observers.js]
|
||||
[test_Preferences.js]
|
||||
[test_addons_engine.js]
|
||||
[test_addons_reconciler.js]
|
||||
[test_addons_store.js]
|
||||
[test_addons_tracker.js]
|
||||
[test_async_chain.js]
|
||||
[test_async_querySpinningly.js]
|
||||
[test_auth_manager.js]
|
||||
[test_bookmark_batch_fail.js]
|
||||
[test_bookmark_engine.js]
|
||||
[test_bookmark_legacy_microsummaries_support.js]
|
||||
[test_bookmark_livemarks.js]
|
||||
[test_bookmark_order.js]
|
||||
[test_bookmark_places_query_rewriting.js]
|
||||
[test_bookmark_record.js]
|
||||
[test_bookmark_smart_bookmarks.js]
|
||||
[test_bookmark_store.js]
|
||||
[test_bookmark_tracker.js]
|
||||
[test_clients_engine.js]
|
||||
[test_clients_escape.js]
|
||||
[test_collection_inc_get.js]
|
||||
[test_collections_recovery.js]
|
||||
[test_corrupt_keys.js]
|
||||
[test_engine.js]
|
||||
[test_engine_abort.js]
|
||||
[test_enginemanager.js]
|
||||
[test_errorhandler.js]
|
||||
[test_errorhandler_filelog.js]
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = os == "android"
|
||||
[test_errorhandler_sync_checkServerError.js]
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = os == "android"
|
||||
[test_forms_store.js]
|
||||
[test_forms_tracker.js]
|
||||
[test_history_engine.js]
|
||||
[test_history_store.js]
|
||||
[test_history_tracker.js]
|
||||
[test_hmac_error.js]
|
||||
[test_httpd_sync_server.js]
|
||||
[test_interval_triggers.js]
|
||||
[test_jpakeclient.js]
|
||||
# Bug 618233: this test produces random failures on Windows 7.
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = os == "win" || os == "android"
|
||||
[test_keys.js]
|
||||
[test_log4moz.js]
|
||||
[test_node_reassignment.js]
|
||||
[test_notifications.js]
|
||||
[test_password_store.js]
|
||||
[test_password_tracker.js]
|
||||
[test_places_guid_downgrade.js]
|
||||
[test_prefs_store.js]
|
||||
[test_prefs_tracker.js]
|
||||
[test_records_crypto.js]
|
||||
[test_records_crypto_generateEntry.js]
|
||||
[test_records_wbo.js]
|
||||
[test_resource.js]
|
||||
[test_resource_async.js]
|
||||
[test_resource_ua.js]
|
||||
[test_restrequest.js]
|
||||
[test_score_triggers.js]
|
||||
[test_sendcredentials_controller.js]
|
||||
[test_service_attributes.js]
|
||||
[test_service_changePassword.js]
|
||||
[test_service_checkAccount.js]
|
||||
[test_service_cluster.js]
|
||||
[test_service_createAccount.js]
|
||||
[test_service_detect_upgrade.js]
|
||||
[test_service_getStorageInfo.js]
|
||||
[test_service_login.js]
|
||||
[test_service_migratePrefs.js]
|
||||
[test_service_passwordUTF8.js]
|
||||
[test_service_persistLogin.js]
|
||||
[test_service_startOver.js]
|
||||
[test_service_startup.js]
|
||||
[test_service_sync_401.js]
|
||||
[test_service_sync_locked.js]
|
||||
[test_service_sync_remoteSetup.js]
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = os == "android"
|
||||
[test_service_sync_updateEnabledEngines.js]
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = os == "android"
|
||||
[test_service_verifyLogin.js]
|
||||
[test_service_wipeClient.js]
|
||||
[test_service_wipeServer.js]
|
||||
[test_status.js]
|
||||
[test_status_checkSetup.js]
|
||||
[test_syncengine.js]
|
||||
[test_syncengine_sync.js]
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = os == "android"
|
||||
[test_syncscheduler.js]
|
||||
[test_syncstoragerequest.js]
|
||||
[test_tab_engine.js]
|
||||
[test_tab_store.js]
|
||||
[test_tab_tracker.js]
|
||||
[test_tracker_addChanged.js]
|
||||
[test_upgrade_old_sync_key.js]
|
||||
# The manifest is roughly ordered from low-level to high-level. When making
|
||||
# systemic sweeping changes, this makes it easier to identify errors closer to
|
||||
# the source.
|
||||
|
||||
# Ensure we can import everything.
|
||||
[test_load_modules.js]
|
||||
|
||||
# util contains a bunch of functionality used throughout.
|
||||
[test_utils_atob.js]
|
||||
[test_utils_catch.js]
|
||||
[test_utils_deepCopy.js]
|
||||
|
@ -129,3 +36,116 @@ skip-if = os == "android"
|
|||
[test_utils_sha1.js]
|
||||
[test_utils_stackTrace.js]
|
||||
[test_utils_utf8.js]
|
||||
|
||||
# We have a number of other libraries that are pretty much standalone.
|
||||
[test_Observers.js]
|
||||
[test_Preferences.js]
|
||||
[test_async_chain.js]
|
||||
[test_async_querySpinningly.js]
|
||||
[test_httpd_sync_server.js]
|
||||
[test_log4moz.js]
|
||||
[test_restrequest.js]
|
||||
[test_jpakeclient.js]
|
||||
# Bug 618233: this test produces random failures on Windows 7.
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = os == "win" || os == "android"
|
||||
|
||||
# HTTP layers.
|
||||
[test_resource.js]
|
||||
[test_resource_async.js]
|
||||
[test_resource_ua.js]
|
||||
[test_syncstoragerequest.js]
|
||||
|
||||
# Generic Sync types.
|
||||
[test_collection_inc_get.js]
|
||||
[test_collections_recovery.js]
|
||||
[test_identity_manager.js]
|
||||
[test_keys.js]
|
||||
[test_records_crypto.js]
|
||||
[test_records_wbo.js]
|
||||
|
||||
# Engine APIs.
|
||||
[test_engine.js]
|
||||
[test_engine_abort.js]
|
||||
[test_enginemanager.js]
|
||||
[test_syncengine.js]
|
||||
[test_syncengine_sync.js]
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = os == "android"
|
||||
[test_tracker_addChanged.js]
|
||||
|
||||
# Service semantics.
|
||||
[test_service_attributes.js]
|
||||
[test_service_changePassword.js]
|
||||
[test_service_checkAccount.js]
|
||||
[test_service_cluster.js]
|
||||
[test_service_createAccount.js]
|
||||
[test_service_detect_upgrade.js]
|
||||
[test_service_getStorageInfo.js]
|
||||
[test_service_login.js]
|
||||
[test_service_migratePrefs.js]
|
||||
[test_service_passwordUTF8.js]
|
||||
[test_service_persistLogin.js]
|
||||
[test_service_startOver.js]
|
||||
[test_service_startup.js]
|
||||
[test_service_sync_401.js]
|
||||
[test_service_sync_locked.js]
|
||||
[test_service_sync_remoteSetup.js]
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = os == "android"
|
||||
[test_service_sync_updateEnabledEngines.js]
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = os == "android"
|
||||
[test_service_verifyLogin.js]
|
||||
[test_service_wipeClient.js]
|
||||
[test_service_wipeServer.js]
|
||||
|
||||
[test_corrupt_keys.js]
|
||||
[test_errorhandler.js]
|
||||
[test_errorhandler_filelog.js]
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = os == "android"
|
||||
[test_errorhandler_sync_checkServerError.js]
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = os == "android"
|
||||
[test_hmac_error.js]
|
||||
[test_interval_triggers.js]
|
||||
[test_node_reassignment.js]
|
||||
[test_notifications.js]
|
||||
[test_score_triggers.js]
|
||||
[test_sendcredentials_controller.js]
|
||||
[test_status.js]
|
||||
[test_status_checkSetup.js]
|
||||
[test_syncscheduler.js]
|
||||
[test_upgrade_old_sync_key.js]
|
||||
|
||||
# Finally, we test each engine.
|
||||
[test_addons_engine.js]
|
||||
[test_addons_reconciler.js]
|
||||
[test_addons_store.js]
|
||||
[test_addons_tracker.js]
|
||||
[test_bookmark_batch_fail.js]
|
||||
[test_bookmark_engine.js]
|
||||
[test_bookmark_legacy_microsummaries_support.js]
|
||||
[test_bookmark_livemarks.js]
|
||||
[test_bookmark_order.js]
|
||||
[test_bookmark_places_query_rewriting.js]
|
||||
[test_bookmark_record.js]
|
||||
[test_bookmark_smart_bookmarks.js]
|
||||
[test_bookmark_store.js]
|
||||
[test_bookmark_tracker.js]
|
||||
[test_clients_engine.js]
|
||||
[test_clients_escape.js]
|
||||
[test_forms_store.js]
|
||||
[test_forms_tracker.js]
|
||||
[test_history_engine.js]
|
||||
[test_history_store.js]
|
||||
[test_history_tracker.js]
|
||||
[test_places_guid_downgrade.js]
|
||||
[test_password_store.js]
|
||||
[test_password_tracker.js]
|
||||
[test_prefs_store.js]
|
||||
[test_prefs_tracker.js]
|
||||
[test_tab_engine.js]
|
||||
[test_tab_store.js]
|
||||
[test_tab_tracker.js]
|
||||
|
|
|
@ -102,9 +102,9 @@ var TPS = {
|
|||
}
|
||||
}
|
||||
catch(e) {}
|
||||
Weave.Service.account = prefs.getCharPref('tps.account.username');
|
||||
Weave.Service.password = prefs.getCharPref('tps.account.password');
|
||||
Weave.Service.passphrase = prefs.getCharPref('tps.account.passphrase');
|
||||
Weave.Identity.account = prefs.getCharPref('tps.account.username');
|
||||
Weave.Identity.basicPassword = prefs.getCharPref('tps.account.password');
|
||||
Weave.Identity.syncKey = prefs.getCharPref('tps.account.passphrase');
|
||||
Weave.Svc.Obs.notify("weave:service:setup-complete");
|
||||
},
|
||||
|
||||
|
|
|
@ -784,17 +784,17 @@ let TPS =
|
|||
// a new sync account
|
||||
Weave.Svc.Prefs.set("admin-secret", account["admin-secret"]);
|
||||
let suffix = account["account-suffix"];
|
||||
Service.account = "tps" + suffix + "@mozilla.com";
|
||||
Service.password = "tps" + suffix + "tps" + suffix;
|
||||
Service.passphrase = Weave.Utils.generatePassphrase();
|
||||
Service.createAccount(Service.account,
|
||||
Service.password,
|
||||
Weave.Identity.account = "tps" + suffix + "@mozilla.com";
|
||||
Weave.Identity.basicPassword = "tps" + suffix + "tps" + suffix;
|
||||
Weave.Identity.syncKey = Weave.Utils.generatePassphrase();
|
||||
Service.createAccount(Weave.Identity.account,
|
||||
Weave.Identity.basicPassword,
|
||||
"dummy1", "dummy2");
|
||||
} else if (account["username"] && account["password"] &&
|
||||
account["passphrase"]) {
|
||||
Service.account = account["username"];
|
||||
Service.password = account["password"];
|
||||
Service.passphrase = account["passphrase"];
|
||||
Weave.Identity.account = account["username"];
|
||||
Weave.Identity.basicPassword = account["password"];
|
||||
Weave.Identity.syncKey = account["passphrase"];
|
||||
} else {
|
||||
this.DumpError("Must specify admin-secret, or " +
|
||||
"username/password/passphrase in the config file");
|
||||
|
|
Загрузка…
Ссылка в новой задаче