зеркало из https://github.com/mozilla/pjs.git
Merge services-central into mozilla-central
This commit is contained in:
Коммит
82fc671e3f
|
@ -3,7 +3,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
|
||||||
Cu.import("resource://services-sync/main.js");
|
Cu.import("resource://services-sync/main.js");
|
||||||
|
|
||||||
let gTests = [ {
|
let gTests = [ {
|
||||||
|
|
|
@ -755,6 +755,130 @@ let Utils = {
|
||||||
return Utils.encodeKeyBase32(atob(encodedKey));
|
return Utils.encodeKeyBase32(atob(encodedKey));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the HTTP MAC SHA-1 for an HTTP request.
|
||||||
|
*
|
||||||
|
* @param identifier
|
||||||
|
* (string) MAC Key Identifier.
|
||||||
|
* @param key
|
||||||
|
* (string) MAC Key.
|
||||||
|
* @param method
|
||||||
|
* (string) HTTP request method.
|
||||||
|
* @param URI
|
||||||
|
* (nsIURI) HTTP request URI.
|
||||||
|
* @param extra
|
||||||
|
* (object) Optional extra parameters. Valid keys are:
|
||||||
|
* nonce_bytes - How many bytes the nonce should be. This defaults
|
||||||
|
* to 8. Note that this many bytes are Base64 encoded, so the
|
||||||
|
* string length of the nonce will be longer than this value.
|
||||||
|
* ts - Timestamp to use. Should only be defined for testing.
|
||||||
|
* nonce - String nonce. Should only be defined for testing as this
|
||||||
|
* function will generate a cryptographically secure random one
|
||||||
|
* if not defined.
|
||||||
|
* ext - Extra string to be included in MAC. Per the HTTP MAC spec,
|
||||||
|
* the format is undefined and thus application specific.
|
||||||
|
* @returns
|
||||||
|
* (object) Contains results of operation and input arguments (for
|
||||||
|
* symmetry). The object has the following keys:
|
||||||
|
*
|
||||||
|
* identifier - (string) MAC Key Identifier (from arguments).
|
||||||
|
* key - (string) MAC Key (from arguments).
|
||||||
|
* method - (string) HTTP request method (from arguments).
|
||||||
|
* hostname - (string) HTTP hostname used (derived from arguments).
|
||||||
|
* port - (string) HTTP port number used (derived from arguments).
|
||||||
|
* mac - (string) Raw HMAC digest bytes.
|
||||||
|
* getHeader - (function) Call to obtain the string Authorization
|
||||||
|
* header value for this invocation.
|
||||||
|
* nonce - (string) Nonce value used.
|
||||||
|
* ts - (number) Integer seconds since Unix epoch that was used.
|
||||||
|
*/
|
||||||
|
computeHTTPMACSHA1: function computeHTTPMACSHA1(identifier, key, method,
|
||||||
|
uri, extra) {
|
||||||
|
let ts = (extra && extra.ts) ? extra.ts : Math.floor(Date.now() / 1000);
|
||||||
|
let nonce_bytes = (extra && extra.nonce_bytes > 0) ? extra.nonce_bytes : 8;
|
||||||
|
|
||||||
|
// We are allowed to use more than the Base64 alphabet if we want.
|
||||||
|
let nonce = (extra && extra.nonce)
|
||||||
|
? extra.nonce
|
||||||
|
: btoa(Utils.generateRandomBytes(nonce_bytes));
|
||||||
|
|
||||||
|
let host = uri.asciiHost;
|
||||||
|
let port;
|
||||||
|
let usedMethod = method.toUpperCase();
|
||||||
|
|
||||||
|
if (uri.port != -1) {
|
||||||
|
port = uri.port;
|
||||||
|
} else if (uri.scheme == "http") {
|
||||||
|
port = "80";
|
||||||
|
} else if (uri.scheme == "https") {
|
||||||
|
port = "443";
|
||||||
|
} else {
|
||||||
|
throw new Error("Unsupported URI scheme: " + uri.scheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
let ext = (extra && extra.ext) ? extra.ext : "";
|
||||||
|
|
||||||
|
let requestString = ts.toString(10) + "\n" +
|
||||||
|
nonce + "\n" +
|
||||||
|
usedMethod + "\n" +
|
||||||
|
uri.path + "\n" +
|
||||||
|
host + "\n" +
|
||||||
|
port + "\n" +
|
||||||
|
ext + "\n";
|
||||||
|
|
||||||
|
let hasher = Utils.makeHMACHasher(Ci.nsICryptoHMAC.SHA1,
|
||||||
|
Utils.makeHMACKey(key));
|
||||||
|
let mac = Utils.digestBytes(requestString, hasher);
|
||||||
|
|
||||||
|
function getHeader() {
|
||||||
|
return Utils.getHTTPMACSHA1Header(this.identifier, this.ts, this.nonce,
|
||||||
|
this.mac, this.ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
identifier: identifier,
|
||||||
|
key: key,
|
||||||
|
method: usedMethod,
|
||||||
|
hostname: host,
|
||||||
|
port: port,
|
||||||
|
mac: mac,
|
||||||
|
nonce: nonce,
|
||||||
|
ts: ts,
|
||||||
|
ext: ext,
|
||||||
|
getHeader: getHeader
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain the HTTP MAC Authorization header value from fields.
|
||||||
|
*
|
||||||
|
* @param identifier
|
||||||
|
* (string) MAC key identifier.
|
||||||
|
* @param ts
|
||||||
|
* (number) Integer seconds since Unix epoch.
|
||||||
|
* @param nonce
|
||||||
|
* (string) Nonce value.
|
||||||
|
* @param mac
|
||||||
|
* (string) Computed HMAC digest (raw bytes).
|
||||||
|
* @param ext
|
||||||
|
* (optional) (string) Extra string content.
|
||||||
|
* @returns
|
||||||
|
* (string) Value to put in Authorization header.
|
||||||
|
*/
|
||||||
|
getHTTPMACSHA1Header: function getHTTPMACSHA1Header(identifier, ts, nonce,
|
||||||
|
mac, ext) {
|
||||||
|
let header ='MAC id="' + identifier + '", ' +
|
||||||
|
'ts="' + ts + '", ' +
|
||||||
|
'nonce="' + nonce + '", ' +
|
||||||
|
'mac="' + btoa(mac) + '"';
|
||||||
|
|
||||||
|
if (!ext) {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
return header += ', ext="' + ext +'"';
|
||||||
|
},
|
||||||
|
|
||||||
makeURI: function Weave_makeURI(URIString) {
|
makeURI: function Weave_makeURI(URIString) {
|
||||||
if (!URIString)
|
if (!URIString)
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -5,7 +5,8 @@ Cu.import("resource://services-sync/async.js");
|
||||||
Cu.import("resource://services-sync/util.js");
|
Cu.import("resource://services-sync/util.js");
|
||||||
Cu.import("resource://services-sync/record.js");
|
Cu.import("resource://services-sync/record.js");
|
||||||
Cu.import("resource://services-sync/engines.js");
|
Cu.import("resource://services-sync/engines.js");
|
||||||
var btoa;
|
let btoa;
|
||||||
|
let atob;
|
||||||
|
|
||||||
let provider = {
|
let provider = {
|
||||||
getFile: function(prop, persistent) {
|
getFile: function(prop, persistent) {
|
||||||
|
@ -39,6 +40,7 @@ function waitForZeroTimer(callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
btoa = Cu.import("resource://services-sync/log4moz.js").btoa;
|
btoa = Cu.import("resource://services-sync/log4moz.js").btoa;
|
||||||
|
atob = Cu.import("resource://services-sync/log4moz.js").atob;
|
||||||
function getTestLogger(component) {
|
function getTestLogger(component) {
|
||||||
return Log4Moz.repository.getLogger("Testing");
|
return Log4Moz.repository.getLogger("Testing");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
const modules = [
|
const modules = [
|
||||||
|
"addonsreconciler.js",
|
||||||
|
"async.js",
|
||||||
"constants.js",
|
"constants.js",
|
||||||
|
"engines/addons.js",
|
||||||
"engines/bookmarks.js",
|
"engines/bookmarks.js",
|
||||||
"engines/clients.js",
|
"engines/clients.js",
|
||||||
"engines/forms.js",
|
"engines/forms.js",
|
||||||
|
@ -11,12 +14,16 @@ const modules = [
|
||||||
"ext/Observers.js",
|
"ext/Observers.js",
|
||||||
"ext/Preferences.js",
|
"ext/Preferences.js",
|
||||||
"identity.js",
|
"identity.js",
|
||||||
|
"jpakeclient.js",
|
||||||
"log4moz.js",
|
"log4moz.js",
|
||||||
"main.js",
|
"main.js",
|
||||||
"notifications.js",
|
"notifications.js",
|
||||||
|
"policies.js",
|
||||||
"record.js",
|
"record.js",
|
||||||
"resource.js",
|
"resource.js",
|
||||||
|
"rest.js",
|
||||||
"service.js",
|
"service.js",
|
||||||
|
"status.js",
|
||||||
"util.js",
|
"util.js",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
Cu.import("resource://services-sync/util.js");
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
initTestLogging();
|
||||||
|
|
||||||
|
run_next_test();
|
||||||
|
}
|
||||||
|
|
||||||
|
add_test(function test_sha1() {
|
||||||
|
_("Ensure HTTP MAC SHA1 generation works as expected.");
|
||||||
|
|
||||||
|
let id = "vmo1txkttblmn51u2p3zk2xiy16hgvm5ok8qiv1yyi86ffjzy9zj0ez9x6wnvbx7";
|
||||||
|
let key = "b8u1cc5iiio5o319og7hh8faf2gi5ym4aq0zwf112cv1287an65fudu5zj7zo7dz";
|
||||||
|
let ts = 1329181221;
|
||||||
|
let method = "GET";
|
||||||
|
let nonce = "wGX71";
|
||||||
|
let uri = Utils.makeURI("http://10.250.2.176/alias/");
|
||||||
|
|
||||||
|
let result = Utils.computeHTTPMACSHA1(id, key, method, uri, {ts: ts,
|
||||||
|
nonce: nonce});
|
||||||
|
|
||||||
|
do_check_eq(btoa(result.mac), "jzh5chjQc2zFEvLbyHnPdX11Yck=");
|
||||||
|
|
||||||
|
do_check_eq(result.getHeader(),
|
||||||
|
'MAC id="vmo1txkttblmn51u2p3zk2xiy16hgvm5ok8qiv1yyi86ffjzy9zj0ez9x6wnvbx7", ' +
|
||||||
|
'ts="1329181221", nonce="wGX71", mac="jzh5chjQc2zFEvLbyHnPdX11Yck="');
|
||||||
|
|
||||||
|
let ext = "EXTRA DATA; foo,bar=1";
|
||||||
|
|
||||||
|
let result = Utils.computeHTTPMACSHA1(id, key, method, uri, {ts: ts,
|
||||||
|
nonce: nonce,
|
||||||
|
ext: ext});
|
||||||
|
do_check_eq(btoa(result.mac), "bNf4Fnt5k6DnhmyipLPkuZroH68=");
|
||||||
|
do_check_eq(result.getHeader(),
|
||||||
|
'MAC id="vmo1txkttblmn51u2p3zk2xiy16hgvm5ok8qiv1yyi86ffjzy9zj0ez9x6wnvbx7", ' +
|
||||||
|
'ts="1329181221", nonce="wGX71", mac="bNf4Fnt5k6DnhmyipLPkuZroH68=", ' +
|
||||||
|
'ext="EXTRA DATA; foo,bar=1"');
|
||||||
|
|
||||||
|
run_next_test();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_test(function test_nonce_length() {
|
||||||
|
_("Ensure custom nonce lengths are honoured.");
|
||||||
|
|
||||||
|
function get_mac(length) {
|
||||||
|
let uri = Utils.makeURI("http://example.com/");
|
||||||
|
return Utils.computeHTTPMACSHA1("foo", "bar", "GET", uri, {
|
||||||
|
nonce_bytes: length
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = get_mac(12);
|
||||||
|
do_check_eq(12, atob(result.nonce).length);
|
||||||
|
|
||||||
|
let result = get_mac(2);
|
||||||
|
do_check_eq(2, atob(result.nonce).length);
|
||||||
|
|
||||||
|
let result = get_mac(0);
|
||||||
|
do_check_eq(8, atob(result.nonce).length);
|
||||||
|
|
||||||
|
let result = get_mac(-1);
|
||||||
|
do_check_eq(8, atob(result.nonce).length);
|
||||||
|
|
||||||
|
run_next_test();
|
||||||
|
});
|
|
@ -2,6 +2,8 @@
|
||||||
head = head_appinfo.js head_helpers.js head_http_server.js
|
head = head_appinfo.js head_helpers.js head_http_server.js
|
||||||
tail =
|
tail =
|
||||||
|
|
||||||
|
[test_load_modules.js]
|
||||||
|
|
||||||
[test_Observers.js]
|
[test_Observers.js]
|
||||||
[test_Preferences.js]
|
[test_Preferences.js]
|
||||||
[test_addons_engine.js]
|
[test_addons_engine.js]
|
||||||
|
@ -49,7 +51,6 @@ skip-if = os == "android"
|
||||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||||
skip-if = os == "win" || os == "android"
|
skip-if = os == "win" || os == "android"
|
||||||
[test_keys.js]
|
[test_keys.js]
|
||||||
[test_load_modules.js]
|
|
||||||
[test_log4moz.js]
|
[test_log4moz.js]
|
||||||
[test_node_reassignment.js]
|
[test_node_reassignment.js]
|
||||||
[test_notifications.js]
|
[test_notifications.js]
|
||||||
|
@ -115,6 +116,7 @@ skip-if = os == "android"
|
||||||
[test_utils_getErrorString.js]
|
[test_utils_getErrorString.js]
|
||||||
[test_utils_getIcon.js]
|
[test_utils_getIcon.js]
|
||||||
[test_utils_hkdfExpand.js]
|
[test_utils_hkdfExpand.js]
|
||||||
|
[test_utils_httpmac.js]
|
||||||
[test_utils_json.js]
|
[test_utils_json.js]
|
||||||
[test_utils_lazyStrings.js]
|
[test_utils_lazyStrings.js]
|
||||||
[test_utils_lock.js]
|
[test_utils_lock.js]
|
||||||
|
|
Загрузка…
Ссылка в новой задаче