Commit e0957c3c authored by Yicheng Li's avatar Yicheng Li Committed by Commit Bot

device/fido: Call ChromeOS platform authenticator's cancel method

This enables WebAuthn flow to be properly cancelled on ChromeOS.

      timeout and observe that ChromeOS UI is dismissed (and Chrome
      shows the timeout message).

Bug: 1150656
Test: Started MakeCredential with test website then waited till
Change-Id: I5403b03dd99fe329ea9009f7544bfefade39815c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2548185
Commit-Queue: Yicheng Li <yichengli@chromium.org>
Reviewed-by: default avatarMartin Kreichgauer <martinkr@google.com>
Cr-Commit-Position: refs/heads/master@{#829068}
parent 58cd22aa
......@@ -39,7 +39,7 @@ base::string16 ChromeOSAuthenticator::GetDisplayName() const {
namespace {
constexpr int kHasCredentialsTimeoutMs = 3000;
constexpr int kShortTimeoutMs = 3000;
AuthenticatorSupportedOptions ChromeOSAuthenticatorOptions() {
AuthenticatorSupportedOptions options;
......@@ -102,14 +102,18 @@ void ChromeOSAuthenticator::MakeCredential(CtapMakeCredentialRequest request,
req.set_user_display_name(request.user.display_name.value());
req.set_resident_credential(request.resident_key_required);
DCHECK(generate_request_id_callback_);
req.set_request_id(generate_request_id_callback_.Run());
DCHECK_EQ(current_request_id_, 0u);
current_request_id_ = generate_request_id_callback_.Run();
req.set_request_id(current_request_id_);
dbus::MethodCall method_call(u2f::kU2FInterface, u2f::kU2FMakeCredential);
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(req);
// Use infinite timeout because Cancel() will be called when the request
// times out.
u2f_proxy->CallMethodWithErrorResponse(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
&method_call, dbus::ObjectProxy::TIMEOUT_INFINITE,
base::BindOnce(&ChromeOSAuthenticator::OnMakeCredentialResp,
weak_factory_.GetWeakPtr(), std::move(request),
std::move(callback)));
......@@ -201,7 +205,9 @@ void ChromeOSAuthenticator::GetAssertion(CtapGetAssertionRequest request,
req.set_client_data_hash(std::string(request.client_data_hash.begin(),
request.client_data_hash.end()));
DCHECK(generate_request_id_callback_);
req.set_request_id(generate_request_id_callback_.Run());
DCHECK_EQ(current_request_id_, 0u);
current_request_id_ = generate_request_id_callback_.Run();
req.set_request_id(current_request_id_);
for (const PublicKeyCredentialDescriptor& descriptor : request.allow_list) {
const std::vector<uint8_t>& id = descriptor.id();
......@@ -212,8 +218,10 @@ void ChromeOSAuthenticator::GetAssertion(CtapGetAssertionRequest request,
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(req);
// Use infinite timeout because Cancel() will be called when the request
// times out.
u2f_proxy->CallMethodWithErrorResponse(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
&method_call, dbus::ObjectProxy::TIMEOUT_INFINITE,
base::BindOnce(&ChromeOSAuthenticator::OnGetAssertionResp,
weak_factory_.GetWeakPtr(), std::move(request),
std::move(callback)));
......@@ -297,7 +305,7 @@ bool ChromeOSAuthenticator::HasCredentialForGetAssertionRequest(
writer.AppendProtoAsArrayOfBytes(req);
std::unique_ptr<dbus::Response> dbus_response =
u2f_proxy->CallMethodAndBlock(&method_call, kHasCredentialsTimeoutMs);
u2f_proxy->CallMethodAndBlock(&method_call, kShortTimeoutMs);
if (!dbus_response) {
FIDO_LOG(ERROR) << "HasCredentials dbus call had no response or timed out";
......@@ -316,6 +324,55 @@ bool ChromeOSAuthenticator::HasCredentialForGetAssertionRequest(
resp.credential_id().size() > 0;
}
void ChromeOSAuthenticator::Cancel() {
if (current_request_id_ == 0u)
return;
dbus::Bus::Options dbus_options;
dbus_options.bus_type = dbus::Bus::SYSTEM;
scoped_refptr<dbus::Bus> bus = new dbus::Bus(dbus_options);
dbus::ObjectProxy* u2f_proxy = bus->GetObjectProxy(
u2f::kU2FServiceName, dbus::ObjectPath(u2f::kU2FServicePath));
if (!u2f_proxy) {
FIDO_LOG(ERROR) << "Couldn't get u2f proxy, cannot cancel request";
return;
}
u2f::CancelWebAuthnFlowRequest req;
req.set_request_id(current_request_id_);
dbus::MethodCall method_call(u2f::kU2FInterface, u2f::kU2FCancelWebAuthnFlow);
dbus::MessageWriter writer(&method_call);
writer.AppendProtoAsArrayOfBytes(req);
// This needs to be non-blocking since canceling the flow involves Ash.
u2f_proxy->CallMethod(&method_call, kShortTimeoutMs,
base::BindOnce(&ChromeOSAuthenticator::OnCancelResp,
weak_factory_.GetWeakPtr()));
}
void ChromeOSAuthenticator::OnCancelResp(dbus::Response* dbus_response) {
if (!dbus_response) {
FIDO_LOG(ERROR)
<< "CancelWebAuthnFlow dbus call had no response or timed out";
return;
}
dbus::MessageReader reader(dbus_response);
u2f::CancelWebAuthnFlowResponse resp;
if (!reader.PopArrayOfBytesAsProto(&resp)) {
FIDO_LOG(ERROR) << "Failed to parse reply for call to CancelWebAuthnFlow";
return;
}
if (!resp.canceled()) {
FIDO_LOG(ERROR) << "Failed to cancel WebAuthn request with id "
<< current_request_id_;
}
current_request_id_ = 0u;
}
bool ChromeOSAuthenticator::IsInPairingMode() const {
return false;
}
......
......@@ -39,7 +39,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ChromeOSAuthenticator
CtapGetAssertionOptions options,
GetAssertionCallback callback) override;
void GetNextAssertion(GetAssertionCallback callback) override {}
void Cancel() override {}
void Cancel() override;
std::string GetId() const override;
base::string16 GetDisplayName() const override;
const base::Optional<AuthenticatorSupportedOptions>& Options() const override;
......@@ -66,6 +66,11 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ChromeOSAuthenticator
dbus::Response* dbus_response,
dbus::ErrorResponse* error);
void OnCancelResp(dbus::Response* dbus_response);
// Current request_id, used for cancelling the request.
uint32_t current_request_id_ = 0u;
// Callback to set request_id in the window property.
base::RepeatingCallback<uint32_t()> generate_request_id_callback_;
base::WeakPtrFactory<ChromeOSAuthenticator> weak_factory_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment