summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/resources/cryptotoken/enroller.js
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/browser/resources/cryptotoken/enroller.js')
-rw-r--r--chromium/chrome/browser/resources/cryptotoken/enroller.js159
1 files changed, 97 insertions, 62 deletions
diff --git a/chromium/chrome/browser/resources/cryptotoken/enroller.js b/chromium/chrome/browser/resources/cryptotoken/enroller.js
index 1ee758e6635..57706a136d6 100644
--- a/chromium/chrome/browser/resources/cryptotoken/enroller.js
+++ b/chromium/chrome/browser/resources/cryptotoken/enroller.js
@@ -41,22 +41,48 @@ function handleWebEnrollRequest(messageSender, request, sendResponse) {
sendResponseOnce(sentResponse, closeable, response, sendResponse);
}
+ function timeout() {
+ sendErrorResponse({errorCode: ErrorCodes.TIMEOUT});
+ }
+
var sender = createSenderFromMessageSender(messageSender);
if (!sender) {
sendErrorResponse({errorCode: ErrorCodes.BAD_REQUEST});
return null;
}
+ if (sender.origin.indexOf('http://') == 0 && !HTTP_ORIGINS_ALLOWED) {
+ sendErrorResponse({errorCode: ErrorCodes.BAD_REQUEST});
+ return null;
+ }
- var enroller =
- validateEnrollRequest(
- sender, request, 'enrollChallenges', 'signData',
- sendErrorResponse, sendSuccessResponse);
- if (enroller) {
- var registerRequests = request['enrollChallenges'];
- var signRequests = getSignRequestsFromEnrollRequest(request, 'signData');
- closeable = /** @type {Closeable} */ (enroller);
- enroller.doEnroll(registerRequests, signRequests, request['appId']);
+ if (!isValidEnrollRequest(request, 'enrollChallenges', 'signData')) {
+ sendErrorResponse({errorCode: ErrorCodes.BAD_REQUEST});
+ return null;
}
+
+ var timeoutValueSeconds = getTimeoutValueFromRequest(request);
+ // Attenuate watchdog timeout value less than the enroller's timeout, so the
+ // watchdog only fires after the enroller could reasonably have called back,
+ // not before.
+ var watchdogTimeoutValueSeconds = attenuateTimeoutInSeconds(
+ timeoutValueSeconds, MINIMUM_TIMEOUT_ATTENUATION_SECONDS / 2);
+ var watchdog = new WatchdogRequestHandler(watchdogTimeoutValueSeconds,
+ timeout);
+ var wrappedErrorCb = watchdog.wrapCallback(sendErrorResponse);
+ var wrappedSuccessCb = watchdog.wrapCallback(sendSuccessResponse);
+
+ var timer = createAttenuatedTimer(
+ FACTORY_REGISTRY.getCountdownFactory(), timeoutValueSeconds);
+ var logMsgUrl = request['logMsgUrl'];
+ var enroller = new Enroller(timer, sender, wrappedErrorCb, wrappedSuccessCb,
+ logMsgUrl);
+ watchdog.setCloseable(/** @type {!Closeable} */ (enroller));
+ closeable = watchdog;
+
+ var registerRequests = request['enrollChallenges'];
+ var signRequests = getSignRequestsFromEnrollRequest(request, 'signData');
+ enroller.doEnroll(registerRequests, signRequests, request['appId']);
+
return closeable;
}
@@ -93,57 +119,51 @@ function handleU2fEnrollRequest(messageSender, request, sendResponse) {
sendResponseOnce(sentResponse, closeable, response, sendResponse);
}
+ function timeout() {
+ sendErrorResponse({errorCode: ErrorCodes.TIMEOUT});
+ }
+
var sender = createSenderFromMessageSender(messageSender);
if (!sender) {
sendErrorResponse({errorCode: ErrorCodes.BAD_REQUEST});
return null;
}
-
- var enroller =
- validateEnrollRequest(
- sender, request, 'registerRequests', 'signRequests',
- sendErrorResponse, sendSuccessResponse, 'registeredKeys');
- if (enroller) {
- var registerRequests = request['registerRequests'];
- var signRequests = getSignRequestsFromEnrollRequest(request,
- 'signRequests', 'registeredKeys');
- closeable = /** @type {Closeable} */ (enroller);
- enroller.doEnroll(registerRequests, signRequests, request['appId']);
+ if (sender.origin.indexOf('http://') == 0 && !HTTP_ORIGINS_ALLOWED) {
+ sendErrorResponse({errorCode: ErrorCodes.BAD_REQUEST});
+ return null;
}
- return closeable;
-}
-/**
- * Validates an enroll request using the given parameters.
- * @param {WebRequestSender} sender The sender of the message.
- * @param {Object} request The web page's enroll request.
- * @param {string} enrollChallengesName The name of the enroll challenges value
- * in the request.
- * @param {string} signChallengesName The name of the sign challenges value in
- * the request.
- * @param {function(U2fError)} errorCb Error callback.
- * @param {function(string, string, (string|undefined))} successCb Success
- * callback.
- * @param {string=} opt_registeredKeysName The name of the registered keys
- * value in the request.
- * @return {Enroller} Enroller object representing the request, if the request
- * is valid, or null if the request is invalid.
- */
-function validateEnrollRequest(sender, request,
- enrollChallengesName, signChallengesName, errorCb, successCb,
- opt_registeredKeysName) {
- if (!isValidEnrollRequest(request, enrollChallengesName,
- signChallengesName, opt_registeredKeysName)) {
- errorCb({errorCode: ErrorCodes.BAD_REQUEST});
+ if (!isValidEnrollRequest(request, 'registerRequests', 'signRequests',
+ 'registeredKeys')) {
+ sendErrorResponse({errorCode: ErrorCodes.BAD_REQUEST});
return null;
}
var timeoutValueSeconds = getTimeoutValueFromRequest(request);
+ // Attenuate watchdog timeout value less than the enroller's timeout, so the
+ // watchdog only fires after the enroller could reasonably have called back,
+ // not before.
+ var watchdogTimeoutValueSeconds = attenuateTimeoutInSeconds(
+ timeoutValueSeconds, MINIMUM_TIMEOUT_ATTENUATION_SECONDS / 2);
+ var watchdog = new WatchdogRequestHandler(watchdogTimeoutValueSeconds,
+ timeout);
+ var wrappedErrorCb = watchdog.wrapCallback(sendErrorResponse);
+ var wrappedSuccessCb = watchdog.wrapCallback(sendSuccessResponse);
+
var timer = createAttenuatedTimer(
FACTORY_REGISTRY.getCountdownFactory(), timeoutValueSeconds);
var logMsgUrl = request['logMsgUrl'];
- var enroller = new Enroller(timer, sender, errorCb, successCb, logMsgUrl);
- return enroller;
+ var enroller = new Enroller(timer, sender, sendErrorResponse,
+ sendSuccessResponse, logMsgUrl);
+ watchdog.setCloseable(/** @type {!Closeable} */ (enroller));
+ closeable = watchdog;
+
+ var registerRequests = request['registerRequests'];
+ var signRequests = getSignRequestsFromEnrollRequest(request,
+ 'signRequests', 'registeredKeys');
+ enroller.doEnroll(registerRequests, signRequests, request['appId']);
+
+ return closeable;
}
/**
@@ -195,7 +215,7 @@ function isValidEnrollRequest(request, enrollChallengesName,
var EnrollChallenge;
/**
- * @param {Array.<EnrollChallenge>} enrollChallenges The enroll challenges to
+ * @param {Array<EnrollChallenge>} enrollChallenges The enroll challenges to
* validate.
* @param {boolean} appIdRequired Whether the appId property is required on
* each challenge.
@@ -233,7 +253,7 @@ function isValidEnrollChallengeArray(enrollChallenges, appIdRequired) {
/**
* Finds the enroll challenge of the given version in the enroll challlenge
* array.
- * @param {Array.<EnrollChallenge>} enrollChallenges The enroll challenges to
+ * @param {Array<EnrollChallenge>} enrollChallenges The enroll challenges to
* search.
* @param {string} version Version to search for.
* @return {?EnrollChallenge} The enroll challenge with the given versions, or
@@ -287,7 +307,7 @@ function makeEnrollResponseData(enrollChallenge, u2fVersion, enrollDataName,
* the request.
* @param {string=} opt_registeredKeysName The name of the registered keys
* value in the request.
- * @return {Array.<SignChallenge>}
+ * @return {Array<SignChallenge>}
*/
function getSignRequestsFromEnrollRequest(request, signChallengesName,
opt_registeredKeysName) {
@@ -336,11 +356,11 @@ function Enroller(timer, sender, errorCb, successCb, opt_logMsgUrl) {
/** @private {boolean} */
this.done_ = false;
- /** @private {Object.<string, string>} */
+ /** @private {Object<string, string>} */
this.browserData_ = {};
- /** @private {Array.<EnrollHelperChallenge>} */
+ /** @private {Array<EnrollHelperChallenge>} */
this.encodedEnrollChallenges_ = [];
- /** @private {Array.<SignHelperChallenge>} */
+ /** @private {Array<SignHelperChallenge>} */
this.encodedSignChallenges_ = [];
// Allow http appIds for http origins. (Broken, but the caller deserves
// what they get.)
@@ -358,16 +378,16 @@ Enroller.DEFAULT_TIMEOUT_MILLIS = 30 * 1000;
/**
* Performs an enroll request with the given enroll and sign challenges.
- * @param {Array.<EnrollChallenge>} enrollChallenges A set of enroll challenges.
- * @param {Array.<SignChallenge>} signChallenges A set of sign challenges for
+ * @param {Array<EnrollChallenge>} enrollChallenges A set of enroll challenges.
+ * @param {Array<SignChallenge>} signChallenges A set of sign challenges for
* existing enrollments for this user and appId.
* @param {string=} opt_appId The app id for the entire request.
*/
Enroller.prototype.doEnroll = function(enrollChallenges, signChallenges,
opt_appId) {
- /** @private {Array.<EnrollChallenge>} */
+ /** @private {Array<EnrollChallenge>} */
this.enrollChallenges_ = enrollChallenges;
- /** @private {Array.<SignChallenge>} */
+ /** @private {Array<SignChallenge>} */
this.signChallenges_ = signChallenges;
/** @private {(string|undefined)} */
this.appId_ = opt_appId;
@@ -393,8 +413,15 @@ Enroller.prototype.approveOrigin_ = function() {
.then(function(result) {
if (self.done_) return;
if (!result) {
- // Origin not approved: fail the result.
- self.notifyError_({errorCode: ErrorCodes.BAD_REQUEST});
+ // Origin not approved: rather than give an explicit indication to
+ // the web page, let a timeout occur.
+ if (self.timer_.expired()) {
+ self.notifyTimeout_();
+ return;
+ }
+ var newTimer = self.timer_.clone(self.notifyTimeout_.bind(self));
+ self.timer_.clearTimeout();
+ self.timer_ = newTimer;
return;
}
self.sendEnrollRequestToHelper_();
@@ -402,6 +429,14 @@ Enroller.prototype.approveOrigin_ = function() {
};
/**
+ * Notifies the caller of a timeout error.
+ * @private
+ */
+Enroller.prototype.notifyTimeout_ = function() {
+ this.notifyError_({errorCode: ErrorCodes.TIMEOUT});
+};
+
+/**
* Performs an enroll request with this instance's enroll and sign challenges,
* by encoding them into a helper request and passing the resulting request to
* the factory registry's helper.
@@ -496,9 +531,9 @@ Enroller.encodeEnrollChallenge_ = function(enrollChallenge, opt_appId) {
/**
* Encodes the given enroll challenges using this enroller's state.
- * @param {Array.<EnrollChallenge>} enrollChallenges The enroll challenges.
+ * @param {Array<EnrollChallenge>} enrollChallenges The enroll challenges.
* @param {string=} opt_appId The app id for the entire request.
- * @return {!Array.<EnrollHelperChallenge>} The encoded enroll challenges.
+ * @return {!Array<EnrollHelperChallenge>} The encoded enroll challenges.
* @private
*/
Enroller.prototype.encodeEnrollChallenges_ = function(enrollChallenges,
@@ -541,7 +576,7 @@ Enroller.prototype.encodeEnrollChallenges_ = function(enrollChallenges,
/**
* Checks the app ids associated with this enroll request, and calls a callback
* with the result of the check.
- * @param {!Array.<string>} enrollAppIds The app ids in the enroll challenge
+ * @param {!Array<string>} enrollAppIds The app ids in the enroll challenge
* portion of the enroll request.
* @param {function(boolean)} cb Called with the result of the check.
* @private
@@ -558,7 +593,7 @@ Enroller.prototype.checkAppIds_ = function(enrollAppIds, cb) {
* Called with the result of checking the origin. When the origin is allowed
* to claim the app ids, begins checking whether the app ids also list the
* origin.
- * @param {!Array.<string>} appIds The app ids.
+ * @param {!Array<string>} appIds The app ids.
* @param {function(boolean)} cb Called with the result of the check.
* @param {boolean} result Whether the origin could claim the app ids.
* @private