mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-27 02:21:46 +00:00
05aa84c996
- Bug 1219711 - Let fake stream take precedence in testing. r=jib (a52bad675a)
- Bug 1207288. Enable the ANGLE shader validator for WebGL 2. r=jgilbert (9583083fe3)
- Bug 1218944. Transform feedback linking should use varyings intead of attribs. r=jgilbert (37742a04e0)
- Bug 1218939. Fixup GetTransformFeedbackVarying. r=jgilbert (5e4ffd63e5)
- Bug 1218559. Implement FindUniformBlockByMappedName. r=jgilbert (0eefbc1012)
- Bug 1215296. Map uniforms from blocks. r=jgilbert (f87ecddafa)
- more byRef to getter_AddRefs (2f5f474265)
- Bug 1217304: P1. Only fire loadeddata once the first frame has been decoded. r=jwwang (8382426465)
- Bug 1217304: P2. Do not transition to HAVE_ENOUGH_DATA readyState until we do have data. r=jwwang (b17554f65f)
- Bug 1207887 - Fix AsyncPanZoomAnimation, WheelScrollAnimation and TextureHost doesn't compile in non-unified build. r=nical (9f893b3584)
- Bug 1145004 - Fix MSE Telemetry VIDEO_MSE_BUFFERING_COUNT - r=cpearce (bdcab5af5a)
- Bug 1205156 - Add telemetry to measure how often getUserMedia is used over non-secure origins r=jib (f456298e6e)
- Bug 1206900: Add telemetry for device types captured with getUserMedia() r=jib,smaug (5e278764dd)
- Bug 1144975 - Video dimensions for tab mirroring can be smaller than the devices display. r=snorp (c5781eca2d)
- Bug 1193075 - add viewport constraints for independent scrolling in tab sharing. r=smaug, r=jesup (f9243c0e97)
- bug 1221855 null-check mInputBuffer in SizeOfExcludingThis() r=padenot (d3cd52cfda)
- Bug 1193075 - make { scrollWithPage: false } not scroll with page. r=jesup (3f4aa04ba4)
- Bug 1212633 - include mobile and unfiled folders in Sync's concept of 'all IDs'. r=rnewman (908001a794)
- Bug 1217077 - Remove for-each from services/. r=gps (98a7a1d49d)
- Bug 1210573 - Add attribute 'packageIdentifier' to nsIPackagedAppUtils. r=valentin. (0115fa1b85)
- Bug 1178518 - Verify signed packages. r=valentin (5decf51ecb)
- Bug 1178518 - Add an AppTrustedRoot for signed packaged app. r=keeler (15e50605b4)
- Bug 1177013 - test_cpows.xul test for CPOW cancelation (r=dvander) (867c40bec1)
- Bug 1215167 - Forbid unsafe browser CPOWs (disabled by default for now) (r=mrbkap) (cee45a21b1)
- Bug 1174487. Stop using JS_ReportPendingException in ThrowAndReport. Just let the AutoJSAPI do the work for us. r=bholley (877d91b8ab)
- Bug 1213289 part 1. Change dom::Throw to take an XPCOM string, not a raw C string, for the message. r=bkelly (d15fbd30d5)
- Bug 1213289 part 2. Introduce ErrorResult::ClearUnionData and use it in various places where we're trying to do that. r=bkelly (c7e5dac146)
- Bug 1213289 part 3. Add a way to throw a DOMException with a custom message on ErrorResult. r=bkelly (aef71f28a9)
- Bug 1213289 part 4. Convert to using an enum for tracking our union state. r=bkelly (def36e74a1)
- Bug 1174593 - Null check context compartment in GetCurrentJSStack(). r=bholley (a785100a75)
- Bug 1216819 - Allow JSAPI SavedFrame accessors to skip past self-hosted frames. r=bz (e7c40f2c30)
- Bug 1200832 - make Console.trace follow async parents; r=baku,bgrins (9694111f6b)
- Bug 1218496 - Add MOZ_COUNT_CTOR/DTOR to ErrorResult::Message. r=bz (53ad08d1d3)
- Bug 1209107 - Only expose module environment object through testing functions r=shu (5fc969293e)
- Bug 930414 - Update module scope chain handling following addition of global lexical scope r=shu (1fc60942f1)
- fix typo (385064acb8)
- Bug 1215341 - Make assignment to const errors runtime TypeErrors in the frontend and interpreter. (r=jandem) (b1f959ad34)
- Bug 930414 - Implement module namespaces r=shu (8c78ae93f2)
- Bug 930414 - Make |this| undefined in modules r=shu (effe64e5ec)
- uBg 930414 - Replace |thisObject| object op with |thisValue| and use if for modules r=shu r=smaug (4875da587e)
- Bug 1125423 part 1 - Attach WindowProxies to globals instead of using innerObject/outerObject hooks. r=bz,luke (ae07ae6add)
- Bug 1125423 part 2 - Rename stopAtOuter argument to *Unwrap functionsto stopAtWindowProxy. r=bz (87334947c7)
- Bug 1125423 part 3 - Use IsWindow/IsWindowProxy functions instead of checking for Class hooks. r=bz (ec479123de)
- Bug 1219183 - Update comments that reference renamed thisObject hook r=shu (d99fd5f5a4)
- Bug 1125423 part 4 - Make GetThisValue infallible, stop invoking the Class hook. r=shu (7780fae25c)
- Bug 1125423 part 5 - Remove innerObject/outerObject/thisValue Class hooks. r=luke (e6798ba62f)
- Bug 1125423 part 6 - Remove nsGlobalWindow::OuterObject and ObjectToOuterObjectValue. r=bz (9c69c88ffc)
- Bug 1217061 - Report OOMs in IonCache::linkAndAttachStub(). r=djvj (6515dfc38f)
- Bug 1215573 - Remove AutoWritableJitCode from IonCache::updateBaseAddress. r=nbp (3b01574971)
- Bug 1209118 part 1 - Add id operand to MGetPropertyCache. r=efaust (d030b03035)
- Bug 1209118 part 2 - Fix GetPropertyIC stubs. r=efaust (3de861379e)
- Bug 1209118 part 3 - Move arguments element stub. r=efaust (90416752ec)
- Bug 1209118 part 4 - Move dense element stub. r=efaust (1c00927242)
- Bug 1209118 part 5 - Move dense element hole stub. r=efaust (888aeac645)
- Bug 1209118 part 6 - Move typed-or-unboxed element stub. r=efaust (1faf3c96eb)
- Bug 1209118 part 7 - Disable GetPropertyIC when the IC fails to attach stubs. r=efaust (ee29616d9e)
- Bug 1209118 part 8 - Use MGetPropertyCache for GETELEM. r=efaust (9ce7df2660)
- Bug 1209118 part 9 - rm MGetElementCache, GetElementIC. r=efaust (0c1747a8f8)
- Bug 1209118 part 10 - Fix a performance issue when disabling GetPropertyIC. r=efaust (c915688ed4)
- Bug 1209118 part 11 - Fix and simplify condition in GetPropertyIC::maybeDisable. r=efaust (051d4bc465)
- Bug 1214562 part 1 - SetElementCache no longer needs a byteop register on x86. r=bhackett (51353013a1)
- Bug 1214163 - Clean up SetPropertyIC::update. r=efaust (a520d092ac)
- Bug 1214562 part 2 - Refactor SetPropertyCache regalloc. r=bhackett (e7be5c651b)
- Bug 1216151 - Ensure the object has a non-lazy group in SetPropertyIC::tryAttachStub. r=efaust (205f6770cb)
- Bug 1213859 - Focus and blur events should not be cancelable; r=smaug (17e8f894d7)
- Bug 848569 - Replace DownloadsLogger with usage of ConsoleAPI. r=paolo (2ecc8e2c21)
- Bug 974718 - the download indicator stayhighlighted after "clear downloads" selected. r=paolo (4b44e45dd5)
- Bug 1146907 - Dismissing the unblock related dialog window unblocks the download. r=paolo (9fa551f5c2)
- mark done (19f3101048)
- Bug 1196047 - Move system.js to devtools/shared. r=jsantell (4c8ba36843)
- Bug 1197967 - preserve spelling of urls in output-parser.js; r=pbrosset (00395d373c)
- Bug 1146935 - StyleEditor: Respect the transition preference when a linked CSS file has changed on disk. r=bgrins (6b65ff1e0f)
- Bug 1206425 - Reorganize CodeMirror file structure for easier upgrades r=bgrins (95b5e26ce3)
- Bug 1132557 - Part 1: Upgrade to CodeMirror 5.7.0 r=bgrins * * * Bug 1132557 - Part 1: Update CodeMirror License r=bgrins * * * Bug 1132557 - Part 2: Upgrade existing addons to CodeMirror 5.7.0 r=bgrins * * * Bug 1132557 - Part 4: Upgrade existing CodeMirror keymap to 5.7.0 r=bgrins * * * Bug 1132557 - Part 5: Upgrade existing CodeMirror mode to 5.7.0 r=bgrins * * * Bug 1132557 - Part 6: Upgrade to CodeMirror 5.7.0 r=bgrins * * * Bug 1132557 - Part 7: Upgrade existing CodeMirror tests to 5.7.0 r=bgrins * * * Bug 1132557 - Part 13: Update CodeMirror README for version 5.7.0 r=bgrins (3435eae2d9)
- Bug 1132557 - Part 2: Apply fixes for CodeMirror 5.7.0 upgrade r=bgrins * * * Bug 1132557 - Part 3: Apply CodeMirror customization for search.js r=bgrins * * * Bug 1132557 - Part 8: Editor config option should be updated r=bgrins * * * Bug 1132557 - Part 9: Editor should emit a cursorActivity on setCursor r=bgrins * * * Bug 1132557 - Part 10: Make Debugger breadrumbs keyboard access test by refocusing the stack frame r=bgrins * * * Bug 1132557 - Part 11: Scratchpad should use capture on the paste event r=bgrins * * * Bug 1132557 - Part 12: Stylesheet Editor should always batch up updates r=bgrins (d4f8c2e49f)
- Bug 984880 - as-authored styles in the rule view; r=pbrosset,r=bgrins (6290c7c0e8)
- Bug 1170864 - Add xpcshell-tests for DevToolsUtils.fetch. r=past Bug 1196047 - Move indentation.js to devtools/shared. r=bgrins (21599da2d7)
- missing bits 1154809 (9516a51799)
- bit of Bug 1142194 - fix quoteString to correctly quote. r=pbrosset (4fb19f01f9)
- Bug 1195356 - make parseDeclarations handle comments; add rewriteDeclarations; r=pbrosset (5fdb22f57b)
- Bug 1195995 - merge css-tokenizer into css-parsing-utils; r=mratcliffe (8959b204f4)
- missing tests (bccf719441)
- Bug 1201949 - Initial redux-style controllers for front end memory tool heap snapshot. r=jlongster (cf2917e645)
- Bug 1196047 - Move async-storage.js to devtools/shared. r=bgrins (dc246d7891)
- Bug 1196047 - Move worker*.js to devtools/shared. r=jsantell (0d5f4d1aec)
- Bug 1196047 - Move most of shared/performance to client or server. r=jsantell (11cd58015a)
- Bug 1196047 - Move shared/shared perf files to server/performance. r=jsantell (9b4348afd2)
- Bug 1196047 - Move tern to client/sourceeditor. r=bgrins (82b81726d3)
614 lines
19 KiB
JavaScript
614 lines
19 KiB
JavaScript
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
|
/* 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";
|
|
|
|
var { Ci, Cc } = require("chrome");
|
|
var Services = require("Services");
|
|
var promise = require("promise");
|
|
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
|
var { dumpn, dumpv } = DevToolsUtils;
|
|
loader.lazyRequireGetter(this, "prompt",
|
|
"devtools/shared/security/prompt");
|
|
loader.lazyRequireGetter(this, "cert",
|
|
"devtools/shared/security/cert");
|
|
loader.lazyRequireGetter(this, "asyncStorage",
|
|
"devtools/shared/async-storage");
|
|
DevToolsUtils.defineLazyModuleGetter(this, "Task",
|
|
"resource://gre/modules/Task.jsm");
|
|
|
|
/**
|
|
* A simple enum-like object with keys mirrored to values.
|
|
* This makes comparison to a specfic value simpler without having to repeat and
|
|
* mis-type the value.
|
|
*/
|
|
function createEnum(obj) {
|
|
for (let key in obj) {
|
|
obj[key] = key;
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
/**
|
|
* |allowConnection| implementations can return various values as their |result|
|
|
* field to indicate what action to take. By specifying these, we can
|
|
* centralize the common actions available, while still allowing embedders to
|
|
* present their UI in whatever way they choose.
|
|
*/
|
|
var AuthenticationResult = exports.AuthenticationResult = createEnum({
|
|
|
|
/**
|
|
* Close all listening sockets, and disable them from opening again.
|
|
*/
|
|
DISABLE_ALL: null,
|
|
|
|
/**
|
|
* Deny the current connection.
|
|
*/
|
|
DENY: null,
|
|
|
|
/**
|
|
* Additional data needs to be exchanged before a result can be determined.
|
|
*/
|
|
PENDING: null,
|
|
|
|
/**
|
|
* Allow the current connection.
|
|
*/
|
|
ALLOW: null,
|
|
|
|
/**
|
|
* Allow the current connection, and persist this choice for future
|
|
* connections from the same client. This requires a trustable mechanism to
|
|
* identify the client in the future, such as the cert used during OOB_CERT.
|
|
*/
|
|
ALLOW_PERSIST: null
|
|
|
|
});
|
|
|
|
/**
|
|
* An |Authenticator| implements an authentication mechanism via various hooks
|
|
* in the client and server debugger socket connection path (see socket.js).
|
|
*
|
|
* |Authenticator|s are stateless objects. Each hook method is passed the state
|
|
* it needs by the client / server code in socket.js.
|
|
*
|
|
* Separate instances of the |Authenticator| are created for each use (client
|
|
* connection, server listener) in case some methods are customized by the
|
|
* embedder for a given use case.
|
|
*/
|
|
var Authenticators = {};
|
|
|
|
/**
|
|
* The Prompt authenticator displays a server-side user prompt that includes
|
|
* connection details, and asks the user to verify the connection. There are
|
|
* no cryptographic properties at work here, so it is up to the user to be sure
|
|
* that the client can be trusted.
|
|
*/
|
|
var Prompt = Authenticators.Prompt = {};
|
|
|
|
Prompt.mode = "PROMPT";
|
|
|
|
Prompt.Client = function() {};
|
|
Prompt.Client.prototype = {
|
|
|
|
mode: Prompt.mode,
|
|
|
|
/**
|
|
* When client has just made a new socket connection, validate the connection
|
|
* to ensure it meets the authenticator's policies.
|
|
*
|
|
* @param host string
|
|
* The host name or IP address of the debugger server.
|
|
* @param port number
|
|
* The port number of the debugger server.
|
|
* @param encryption boolean (optional)
|
|
* Whether the server requires encryption. Defaults to false.
|
|
* @param cert object (optional)
|
|
* The server's cert details.
|
|
* @param s nsISocketTransport
|
|
* Underlying socket transport, in case more details are needed.
|
|
* @return boolean
|
|
* Whether the connection is valid.
|
|
*/
|
|
validateConnection() {
|
|
return true;
|
|
},
|
|
|
|
/**
|
|
* Work with the server to complete any additional steps required by this
|
|
* authenticator's policies.
|
|
*
|
|
* Debugging commences after this hook completes successfully.
|
|
*
|
|
* @param host string
|
|
* The host name or IP address of the debugger server.
|
|
* @param port number
|
|
* The port number of the debugger server.
|
|
* @param encryption boolean (optional)
|
|
* Whether the server requires encryption. Defaults to false.
|
|
* @param transport DebuggerTransport
|
|
* A transport that can be used to communicate with the server.
|
|
* @return A promise can be used if there is async behavior.
|
|
*/
|
|
authenticate() {},
|
|
|
|
};
|
|
|
|
Prompt.Server = function() {};
|
|
Prompt.Server.prototype = {
|
|
|
|
mode: Prompt.mode,
|
|
|
|
/**
|
|
* Verify that listener settings are appropriate for this authentication mode.
|
|
*
|
|
* @param listener SocketListener
|
|
* The socket listener about to be opened.
|
|
* @throws if validation requirements are not met
|
|
*/
|
|
validateOptions() {},
|
|
|
|
/**
|
|
* Augment options on the listening socket about to be opened.
|
|
*
|
|
* @param listener SocketListener
|
|
* The socket listener about to be opened.
|
|
* @param socket nsIServerSocket
|
|
* The socket that is about to start listening.
|
|
*/
|
|
augmentSocketOptions() {},
|
|
|
|
/**
|
|
* Augment the service discovery advertisement with any additional data needed
|
|
* to support this authentication mode.
|
|
*
|
|
* @param listener SocketListener
|
|
* The socket listener that was just opened.
|
|
* @param advertisement object
|
|
* The advertisement being built.
|
|
*/
|
|
augmentAdvertisement(listener, advertisement) {
|
|
advertisement.authentication = Prompt.mode;
|
|
},
|
|
|
|
/**
|
|
* Determine whether a connection the server should be allowed or not based on
|
|
* this authenticator's policies.
|
|
*
|
|
* @param session object
|
|
* In PROMPT mode, the |session| includes:
|
|
* {
|
|
* client: {
|
|
* host,
|
|
* port
|
|
* },
|
|
* server: {
|
|
* host,
|
|
* port
|
|
* },
|
|
* transport
|
|
* }
|
|
* @return An AuthenticationResult value.
|
|
* A promise that will be resolved to the above is also allowed.
|
|
*/
|
|
authenticate({ client, server }) {
|
|
if (!Services.prefs.getBoolPref("devtools.debugger.prompt-connection")) {
|
|
return AuthenticationResult.ALLOW;
|
|
}
|
|
return this.allowConnection({
|
|
authentication: this.mode,
|
|
client,
|
|
server
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Prompt the user to accept or decline the incoming connection. The default
|
|
* implementation is used unless this is overridden on a particular
|
|
* authenticator instance.
|
|
*
|
|
* It is expected that the implementation of |allowConnection| will show a
|
|
* prompt to the user so that they can allow or deny the connection.
|
|
*
|
|
* @param session object
|
|
* In PROMPT mode, the |session| includes:
|
|
* {
|
|
* authentication: "PROMPT",
|
|
* client: {
|
|
* host,
|
|
* port
|
|
* },
|
|
* server: {
|
|
* host,
|
|
* port
|
|
* }
|
|
* }
|
|
* @return An AuthenticationResult value.
|
|
* A promise that will be resolved to the above is also allowed.
|
|
*/
|
|
allowConnection: prompt.Server.defaultAllowConnection,
|
|
|
|
};
|
|
|
|
/**
|
|
* The out-of-band (OOB) cert authenticator is based on self-signed X.509 certs
|
|
* at both the client and server end.
|
|
*
|
|
* The user is first prompted to verify the connection, similar to the prompt
|
|
* method above. This prompt may display cert fingerprints if desired.
|
|
*
|
|
* Assuming the user approves the connection, further UI is used to assist the
|
|
* user in tranferring out-of-band (OOB) verification of the client's
|
|
* certificate. For example, this could take the form of a QR code that the
|
|
* client displays which is then scanned by a camera on the server.
|
|
*
|
|
* Since it is assumed that an attacker can't forge the client's X.509 cert, the
|
|
* user may also choose to always allow a client, which would permit immediate
|
|
* connections in the future with no user interaction needed.
|
|
*
|
|
* See docs/wifi.md for details of the authentication design.
|
|
*/
|
|
var OOBCert = Authenticators.OOBCert = {};
|
|
|
|
OOBCert.mode = "OOB_CERT";
|
|
|
|
OOBCert.Client = function() {};
|
|
OOBCert.Client.prototype = {
|
|
|
|
mode: OOBCert.mode,
|
|
|
|
/**
|
|
* When client has just made a new socket connection, validate the connection
|
|
* to ensure it meets the authenticator's policies.
|
|
*
|
|
* @param host string
|
|
* The host name or IP address of the debugger server.
|
|
* @param port number
|
|
* The port number of the debugger server.
|
|
* @param encryption boolean (optional)
|
|
* Whether the server requires encryption. Defaults to false.
|
|
* @param cert object (optional)
|
|
* The server's cert details.
|
|
* @param socket nsISocketTransport
|
|
* Underlying socket transport, in case more details are needed.
|
|
* @return boolean
|
|
* Whether the connection is valid.
|
|
*/
|
|
validateConnection({ cert, socket }) {
|
|
// Step B.7
|
|
// Client verifies that Server's cert matches hash(ServerCert) from the
|
|
// advertisement
|
|
dumpv("Validate server cert hash");
|
|
let serverCert = socket.securityInfo.QueryInterface(Ci.nsISSLStatusProvider)
|
|
.SSLStatus.serverCert;
|
|
let advertisedCert = cert;
|
|
if (serverCert.sha256Fingerprint != advertisedCert.sha256) {
|
|
dumpn("Server cert hash doesn't match advertisement");
|
|
return false;
|
|
}
|
|
return true;
|
|
},
|
|
|
|
/**
|
|
* Work with the server to complete any additional steps required by this
|
|
* authenticator's policies.
|
|
*
|
|
* Debugging commences after this hook completes successfully.
|
|
*
|
|
* @param host string
|
|
* The host name or IP address of the debugger server.
|
|
* @param port number
|
|
* The port number of the debugger server.
|
|
* @param encryption boolean (optional)
|
|
* Whether the server requires encryption. Defaults to false.
|
|
* @param cert object (optional)
|
|
* The server's cert details.
|
|
* @param transport DebuggerTransport
|
|
* A transport that can be used to communicate with the server.
|
|
* @return A promise can be used if there is async behavior.
|
|
*/
|
|
authenticate({ host, port, cert, transport }) {
|
|
let deferred = promise.defer();
|
|
let oobData;
|
|
|
|
let activeSendDialog;
|
|
let closeDialog = () => {
|
|
// Close any prompts the client may have been showing from previous
|
|
// authentication steps
|
|
if (activeSendDialog && activeSendDialog.close) {
|
|
activeSendDialog.close();
|
|
activeSendDialog = null;
|
|
}
|
|
};
|
|
|
|
transport.hooks = {
|
|
onPacket: Task.async(function*(packet) {
|
|
closeDialog();
|
|
let { authResult } = packet;
|
|
switch (authResult) {
|
|
case AuthenticationResult.PENDING:
|
|
// Step B.8
|
|
// Client creates hash(ClientCert) + K(random 128-bit number)
|
|
oobData = yield this._createOOB();
|
|
activeSendDialog = this.sendOOB({
|
|
host,
|
|
port,
|
|
cert,
|
|
authResult,
|
|
oob: oobData
|
|
});
|
|
break;
|
|
case AuthenticationResult.ALLOW:
|
|
case AuthenticationResult.ALLOW_PERSIST:
|
|
// Step B.12
|
|
// Client verifies received value matches K
|
|
if (packet.k != oobData.k) {
|
|
transport.close(new Error("Auth secret mismatch"));
|
|
return;
|
|
}
|
|
// Step B.13
|
|
// Debugging begins
|
|
transport.hooks = null;
|
|
deferred.resolve(transport);
|
|
break;
|
|
default:
|
|
transport.close(new Error("Invalid auth result: " + authResult));
|
|
return;
|
|
}
|
|
}.bind(this)),
|
|
onClosed(reason) {
|
|
closeDialog();
|
|
// Transport died before auth completed
|
|
transport.hooks = null;
|
|
deferred.reject(reason);
|
|
}
|
|
};
|
|
transport.ready();
|
|
return deferred.promise;
|
|
},
|
|
|
|
/**
|
|
* Create the package of data that needs to be transferred across the OOB
|
|
* channel.
|
|
*/
|
|
_createOOB: Task.async(function*() {
|
|
let clientCert = yield cert.local.getOrCreate();
|
|
return {
|
|
sha256: clientCert.sha256Fingerprint,
|
|
k: this._createRandom()
|
|
};
|
|
}),
|
|
|
|
_createRandom() {
|
|
const length = 16; // 16 bytes / 128 bits
|
|
let rng = Cc["@mozilla.org/security/random-generator;1"]
|
|
.createInstance(Ci.nsIRandomGenerator);
|
|
let bytes = rng.generateRandomBytes(length);
|
|
return bytes.map(byte => byte.toString(16)).join("");
|
|
},
|
|
|
|
/**
|
|
* Send data across the OOB channel to the server to authenticate the devices.
|
|
*
|
|
* @param host string
|
|
* The host name or IP address of the debugger server.
|
|
* @param port number
|
|
* The port number of the debugger server.
|
|
* @param cert object (optional)
|
|
* The server's cert details.
|
|
* @param authResult AuthenticationResult
|
|
* Authentication result sent from the server.
|
|
* @param oob object (optional)
|
|
* The token data to be transferred during OOB_CERT step 8:
|
|
* * sha256: hash(ClientCert)
|
|
* * k : K(random 128-bit number)
|
|
* @return object containing:
|
|
* * close: Function to hide the notification
|
|
*/
|
|
sendOOB: prompt.Client.defaultSendOOB,
|
|
|
|
};
|
|
|
|
OOBCert.Server = function() {};
|
|
OOBCert.Server.prototype = {
|
|
|
|
mode: OOBCert.mode,
|
|
|
|
/**
|
|
* Verify that listener settings are appropriate for this authentication mode.
|
|
*
|
|
* @param listener SocketListener
|
|
* The socket listener about to be opened.
|
|
* @throws if validation requirements are not met
|
|
*/
|
|
validateOptions(listener) {
|
|
if (!listener.encryption) {
|
|
throw new Error(OOBCert.mode + " authentication requires encryption.");
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Augment options on the listening socket about to be opened.
|
|
*
|
|
* @param listener SocketListener
|
|
* The socket listener about to be opened.
|
|
* @param socket nsIServerSocket
|
|
* The socket that is about to start listening.
|
|
*/
|
|
augmentSocketOptions(listener, socket) {
|
|
let requestCert = Ci.nsITLSServerSocket.REQUIRE_ALWAYS;
|
|
socket.setRequestClientCertificate(requestCert);
|
|
},
|
|
|
|
/**
|
|
* Augment the service discovery advertisement with any additional data needed
|
|
* to support this authentication mode.
|
|
*
|
|
* @param listener SocketListener
|
|
* The socket listener that was just opened.
|
|
* @param advertisement object
|
|
* The advertisement being built.
|
|
*/
|
|
augmentAdvertisement(listener, advertisement) {
|
|
advertisement.authentication = OOBCert.mode;
|
|
// Step A.4
|
|
// Server announces itself via service discovery
|
|
// Announcement contains hash(ServerCert) as additional data
|
|
advertisement.cert = listener.cert;
|
|
},
|
|
|
|
/**
|
|
* Determine whether a connection the server should be allowed or not based on
|
|
* this authenticator's policies.
|
|
*
|
|
* @param session object
|
|
* In OOB_CERT mode, the |session| includes:
|
|
* {
|
|
* client: {
|
|
* host,
|
|
* port,
|
|
* cert: {
|
|
* sha256
|
|
* },
|
|
* },
|
|
* server: {
|
|
* host,
|
|
* port,
|
|
* cert: {
|
|
* sha256
|
|
* }
|
|
* },
|
|
* transport
|
|
* }
|
|
* @return An AuthenticationResult value.
|
|
* A promise that will be resolved to the above is also allowed.
|
|
*/
|
|
authenticate: Task.async(function*({ client, server, transport }) {
|
|
// Step B.3 / C.3
|
|
// TLS connection established, authentication begins
|
|
// TODO: Bug 1032128: Consult a list of persisted, approved clients
|
|
// Step B.4
|
|
// Server sees that ClientCert is from a unknown client
|
|
// Tell client they are unknown and should display OOB client UX
|
|
transport.send({
|
|
authResult: AuthenticationResult.PENDING
|
|
});
|
|
|
|
// Step B.5
|
|
// User is shown a Allow / Deny / Always Allow prompt on the Server
|
|
// with Client name and hash(ClientCert)
|
|
let result = yield this.allowConnection({
|
|
authentication: this.mode,
|
|
client,
|
|
server
|
|
});
|
|
|
|
switch (result) {
|
|
case AuthenticationResult.ALLOW_PERSIST:
|
|
// TODO: Bug 1032128: Persist the client
|
|
case AuthenticationResult.ALLOW:
|
|
break; // Further processing
|
|
default:
|
|
return result; // Abort for any negative results
|
|
}
|
|
|
|
// Examine additional data for authentication
|
|
let oob = yield this.receiveOOB();
|
|
if (!oob) {
|
|
dumpn("Invalid OOB data received");
|
|
return AuthenticationResult.DENY;
|
|
}
|
|
|
|
let { sha256, k } = oob;
|
|
// The OOB auth prompt should have transferred:
|
|
// hash(ClientCert) + K(random 128-bit number)
|
|
// from the client.
|
|
if (!sha256 || !k) {
|
|
dumpn("Invalid OOB data received");
|
|
return AuthenticationResult.DENY;
|
|
}
|
|
|
|
// Step B.10
|
|
// Server verifies that Client's cert matches hash(ClientCert) from
|
|
// out-of-band channel
|
|
if (client.cert.sha256 != sha256) {
|
|
dumpn("Client cert hash doesn't match OOB data");
|
|
return AuthenticationResult.DENY;
|
|
}
|
|
|
|
// Step B.11
|
|
// Server sends K to Client over TLS connection
|
|
transport.send({ authResult: result, k });
|
|
|
|
// Client may decide to abort if K does not match.
|
|
// Server's portion of authentication is now complete.
|
|
|
|
// Step B.13
|
|
// Debugging begins
|
|
return result;
|
|
}),
|
|
|
|
/**
|
|
* Prompt the user to accept or decline the incoming connection. The default
|
|
* implementation is used unless this is overridden on a particular
|
|
* authenticator instance.
|
|
*
|
|
* It is expected that the implementation of |allowConnection| will show a
|
|
* prompt to the user so that they can allow or deny the connection.
|
|
*
|
|
* @param session object
|
|
* In OOB_CERT mode, the |session| includes:
|
|
* {
|
|
* authentication: "OOB_CERT",
|
|
* client: {
|
|
* host,
|
|
* port,
|
|
* cert: {
|
|
* sha256
|
|
* },
|
|
* },
|
|
* server: {
|
|
* host,
|
|
* port,
|
|
* cert: {
|
|
* sha256
|
|
* }
|
|
* }
|
|
* }
|
|
* @return An AuthenticationResult value.
|
|
* A promise that will be resolved to the above is also allowed.
|
|
*/
|
|
allowConnection: prompt.Server.defaultAllowConnection,
|
|
|
|
/**
|
|
* The user must transfer some data through some out of band mechanism from
|
|
* the client to the server to authenticate the devices.
|
|
*
|
|
* @return An object containing:
|
|
* * sha256: hash(ClientCert)
|
|
* * k : K(random 128-bit number)
|
|
* A promise that will be resolved to the above is also allowed.
|
|
*/
|
|
receiveOOB: prompt.Server.defaultReceiveOOB,
|
|
|
|
};
|
|
|
|
exports.Authenticators = {
|
|
get(mode) {
|
|
if (!mode) {
|
|
mode = Prompt.mode;
|
|
}
|
|
for (let key in Authenticators) {
|
|
let auth = Authenticators[key];
|
|
if (auth.mode === mode) {
|
|
return auth;
|
|
}
|
|
}
|
|
throw new Error("Unknown authenticator mode: " + mode);
|
|
}
|
|
};
|