summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Kreichgauer <martinkr@google.com>2020-06-03 21:07:08 +0000
committerMichael BrĂ¼ning <michael.bruning@qt.io>2020-08-03 13:35:59 +0000
commit8bf68f5a9c39a6260a7698dbe517f2fc807f1836 (patch)
tree8b4537b7761fc55fe2968462bf1f2cf2d14279f1
parent8a0c6063c5be01ce6cb1eda5dd671453ef7f60c4 (diff)
downloadqtwebengine-chromium-8bf68f5a9c39a6260a7698dbe517f2fc807f1836.tar.gz
[Backport] Security bug 1087158
Manual backport of patch originally reviewed on https://chromium-review.googlesource.com/c/chromium/src/+/2228136: Revert "fido: add FidoDiscoveryFactory::ResetRequestState()" This reverts commit 9f151687295d2547bc3d7c1542b80505552f0f87. Reason for revert: The original change makes an invalid assumptions about the lifetime of FidoDiscoveryFactory (crbug/1087158). Instances of FidoDiscoveryFactory generally belong to the AuthenticatorRequestClientDelegate and as such should outlive the WebAuthn request. As an exception, instances obtained via AuthenticatorEnvironmentImpl::GetDiscoveryFactoryOverride() may be unregistered and freed before the request finishes. This revert is safe because the caBLE data reset by ResetRequestState (a) only gets set in the first place if the WebAuthenticationPhoneSupport flag is on (which is default-off); and (b) gets set anew for every single request, so it will never be reused across requests. Bug: 1087158 Original change's description: > fido: add FidoDiscoveryFactory::ResetRequestState() > > FidoDiscoveryFactory instances generally outlive a WebAuthn request, but > some of the state is specific to a single request (caBLE pairing and QR > code generation keys). This is currently not an issue, because > AuthenticatorCommon explicitly resets all that state at the beginning of > the request. But I worry that we accidentally break that and leak state > between requests. To mitigate, introduce an explicit ResetRequestState > function and call it in AuthenticatorCommon::Cleanup(). > > Change-Id: I8333a3b14d189d7977cde17cbfe44b4b8dcf6ee2 > Reviewed-on: > https://chromium-review.googlesource.com/c/chromium/src/+/1793792 > Commit-Queue: Martin Kreichgauer <martinkr@chromium.org> > Reviewed-by: Nina Satragno <nsatragno@chromium.org> > Reviewed-by: Adam Langley <agl@chromium.org> > Cr-Commit-Position: refs/heads/master@{#696593} Reviewed-by: Nina Satragno <nsatragno@chromium.org> Reviewed-by: Adam Langley <agl@chromium.org> Commit-Queue: Martin Kreichgauer <martinkr@google.com> Cr-Commit-Position: refs/heads/master@{#774784} Change-Id: I75c800d5370ce9d7003846985d038cd566739be5 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r--chromium/content/browser/webauth/authenticator_common.cc29
-rw-r--r--chromium/content/browser/webauth/authenticator_common.h1
-rw-r--r--chromium/device/fido/fido_discovery_factory.cc22
-rw-r--r--chromium/device/fido/fido_discovery_factory.h30
4 files changed, 21 insertions, 61 deletions
diff --git a/chromium/content/browser/webauth/authenticator_common.cc b/chromium/content/browser/webauth/authenticator_common.cc
index cea81abea6f..793c7c5f2d2 100644
--- a/chromium/content/browser/webauth/authenticator_common.cc
+++ b/chromium/content/browser/webauth/authenticator_common.cc
@@ -579,12 +579,12 @@ AuthenticatorCommon::CreateRequestDelegate(std::string relying_party_id) {
void AuthenticatorCommon::StartMakeCredentialRequest(
bool allow_skipping_pin_touch) {
- discovery_factory_ =
+ device::FidoDiscoveryFactory* discovery_factory =
AuthenticatorEnvironmentImpl::GetInstance()->GetDiscoveryFactoryOverride(
static_cast<RenderFrameHostImpl*>(render_frame_host_)
->frame_tree_node());
- if (!discovery_factory_) {
- discovery_factory_ = request_delegate_->GetDiscoveryFactory();
+ if (!discovery_factory) {
+ discovery_factory = request_delegate_->GetDiscoveryFactory();
}
if (base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport)) {
@@ -597,13 +597,13 @@ void AuthenticatorCommon::StartMakeCredentialRequest(
if (request_delegate_->SetCableTransportInfo(
/*cable_extension_provided=*/false, have_paired_phones,
qr_generator_key)) {
- discovery_factory_->set_cable_data(cable_pairings,
+ discovery_factory->set_cable_data(cable_pairings,
std::move(qr_generator_key));
}
}
request_ = std::make_unique<device::MakeCredentialRequestHandler>(
- connector_, discovery_factory_,
+ connector_, discovery_factory,
GetTransports(caller_origin_, transports_),
*ctap_make_credential_request_, *authenticator_selection_criteria_,
allow_skipping_pin_touch,
@@ -634,12 +634,12 @@ void AuthenticatorCommon::StartMakeCredentialRequest(
void AuthenticatorCommon::StartGetAssertionRequest(
bool allow_skipping_pin_touch) {
- discovery_factory_ =
+ device::FidoDiscoveryFactory* discovery_factory =
AuthenticatorEnvironmentImpl::GetInstance()->GetDiscoveryFactoryOverride(
static_cast<RenderFrameHostImpl*>(render_frame_host_)
->frame_tree_node());
- if (!discovery_factory_) {
- discovery_factory_ = request_delegate_->GetDiscoveryFactory();
+ if (!discovery_factory) {
+ discovery_factory = request_delegate_->GetDiscoveryFactory();
}
std::vector<device::CableDiscoveryData> cable_pairings;
@@ -664,12 +664,12 @@ void AuthenticatorCommon::StartGetAssertionRequest(
if ((!cable_pairings.empty() || qr_generator_key.has_value()) &&
request_delegate_->SetCableTransportInfo(
have_cable_extension, have_paired_phones, qr_generator_key)) {
- discovery_factory_->set_cable_data(std::move(cable_pairings),
+ discovery_factory->set_cable_data(std::move(cable_pairings),
std::move(qr_generator_key));
}
request_ = std::make_unique<device::GetAssertionRequestHandler>(
- connector_, discovery_factory_,
+ connector_, discovery_factory,
GetTransports(caller_origin_, transports_), *ctap_get_assertion_request_,
allow_skipping_pin_touch,
base::BindOnce(&AuthenticatorCommon::OnSignResponse,
@@ -1528,15 +1528,6 @@ void AuthenticatorCommon::Cleanup() {
timer_->Stop();
request_.reset();
- if (discovery_factory_) {
- // The FidoDiscoveryFactory instance may have been obtained via
- // AuthenticatorEnvironmentImpl::GetDiscoveryFactoryOverride() (in unit
- // tests or when WebDriver injected a virtual authenticator), in which case
- // it may be long-lived and handle more than one request. Hence, we need to
- // reset all per-request state before deleting its pointer.
- discovery_factory_->ResetRequestState();
- discovery_factory_ = nullptr;
- }
request_delegate_.reset();
make_credential_response_callback_.Reset();
get_assertion_response_callback_.Reset();
diff --git a/chromium/content/browser/webauth/authenticator_common.h b/chromium/content/browser/webauth/authenticator_common.h
index a7879a77f33..bd241cc8fc3 100644
--- a/chromium/content/browser/webauth/authenticator_common.h
+++ b/chromium/content/browser/webauth/authenticator_common.h
@@ -194,7 +194,6 @@ class CONTENT_EXPORT AuthenticatorCommon {
RenderFrameHost* const render_frame_host_;
service_manager::Connector* connector_ = nullptr;
base::flat_set<device::FidoTransportProtocol> transports_;
- device::FidoDiscoveryFactory* discovery_factory_ = nullptr;
std::unique_ptr<device::FidoRequestHandlerBase> request_;
blink::mojom::Authenticator::MakeCredentialCallback
make_credential_response_callback_;
diff --git a/chromium/device/fido/fido_discovery_factory.cc b/chromium/device/fido/fido_discovery_factory.cc
index 05d5f211b17..dc404ba31c2 100644
--- a/chromium/device/fido/fido_discovery_factory.cc
+++ b/chromium/device/fido/fido_discovery_factory.cc
@@ -46,10 +46,6 @@ std::unique_ptr<FidoDiscoveryBase> CreateUsbFidoDiscovery(
FidoDiscoveryFactory::FidoDiscoveryFactory() = default;
FidoDiscoveryFactory::~FidoDiscoveryFactory() = default;
-void FidoDiscoveryFactory::ResetRequestState() {
- request_state_ = {};
-}
-
std::unique_ptr<FidoDiscoveryBase> FidoDiscoveryFactory::Create(
FidoTransportProtocol transport,
service_manager::Connector* connector) {
@@ -59,13 +55,10 @@ std::unique_ptr<FidoDiscoveryBase> FidoDiscoveryFactory::Create(
case FidoTransportProtocol::kBluetoothLowEnergy:
return std::make_unique<FidoBleDiscovery>();
case FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy:
- if (request_state_.cable_data_.has_value() ||
- request_state_.qr_generator_key_.has_value()) {
+ if (cable_data_.has_value() || qr_generator_key_.has_value()) {
return std::make_unique<FidoCableDiscovery>(
- request_state_.cable_data_.value_or(
- std::vector<CableDiscoveryData>()),
- request_state_.qr_generator_key_,
- request_state_.cable_pairing_callback_);
+ cable_data_.value_or(std::vector<CableDiscoveryData>()),
+ qr_generator_key_, cable_pairing_callback_);
}
return nullptr;
case FidoTransportProtocol::kNearFieldCommunication:
@@ -88,14 +81,14 @@ std::unique_ptr<FidoDiscoveryBase> FidoDiscoveryFactory::Create(
void FidoDiscoveryFactory::set_cable_data(
std::vector<CableDiscoveryData> cable_data,
base::Optional<QRGeneratorKey> qr_generator_key) {
- request_state_.cable_data_ = std::move(cable_data);
- request_state_.qr_generator_key_ = std::move(qr_generator_key);
+ cable_data_ = std::move(cable_data);
+ qr_generator_key_ = std::move(qr_generator_key);
}
void FidoDiscoveryFactory::set_cable_pairing_callback(
base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)>
pairing_callback) {
- request_state_.cable_pairing_callback_.emplace(std::move(pairing_callback));
+ cable_pairing_callback_.emplace(std::move(pairing_callback));
}
#if defined(OS_WIN)
@@ -121,7 +114,4 @@ FidoDiscoveryFactory::MaybeCreateWinWebAuthnApiDiscovery() {
}
#endif // defined(OS_WIN)
-FidoDiscoveryFactory::RequestState::RequestState() = default;
-FidoDiscoveryFactory::RequestState::~RequestState() = default;
-
} // namespace device
diff --git a/chromium/device/fido/fido_discovery_factory.h b/chromium/device/fido/fido_discovery_factory.h
index 63133e7dc2b..3723225f316 100644
--- a/chromium/device/fido/fido_discovery_factory.h
+++ b/chromium/device/fido/fido_discovery_factory.h
@@ -38,18 +38,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory {
FidoDiscoveryFactory();
virtual ~FidoDiscoveryFactory();
- // Resets all fields that are only meaningful for the duration of a single
- // request to a safe default.
- //
- // The "regular" FidoDiscoveryFactory is owned by the
- // AuthenticatorClientRequestDelegate and lives only for a single request.
- // Instances returned from
- // AuthenticatorEnvironmentImpl::GetDiscoveryFactoryOverride(), which are
- // used in unit tests or by the WebDriver virtual authenticators, are
- // long-lived and may handle multiple WebAuthn requests. Hence, they will be
- // reset at the beginning of each new request.
- void ResetRequestState();
-
// Instantiates a FidoDiscoveryBase for the given transport.
//
// FidoTransportProtocol::kUsbHumanInterfaceDevice requires specifying a
@@ -89,22 +77,14 @@ class COMPONENT_EXPORT(DEVICE_FIDO) FidoDiscoveryFactory {
#endif // defined(OS_WIN)
private:
- // RequestState holds configuration data that is only meaningful for a
- // single WebAuthn request.
- struct RequestState {
- RequestState();
- ~RequestState();
- base::Optional<std::vector<CableDiscoveryData>> cable_data_;
- base::Optional<QRGeneratorKey> qr_generator_key_;
- base::Optional<
- base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)>>
- cable_pairing_callback_;
- };
-
- RequestState request_state_;
#if defined(OS_MACOSX)
base::Optional<fido::mac::AuthenticatorConfig> mac_touch_id_config_;
#endif // defined(OS_MACOSX)
+ base::Optional<std::vector<CableDiscoveryData>> cable_data_;
+ base::Optional<QRGeneratorKey> qr_generator_key_;
+ base::Optional<
+ base::RepeatingCallback<void(std::unique_ptr<CableDiscoveryData>)>>
+ cable_pairing_callback_;
#if defined(OS_WIN)
WinWebAuthnApi* win_webauthn_api_ = nullptr;
#endif // defined(OS_WIN)