Commit bcfda9cf authored by Martin Kreichgauer's avatar Martin Kreichgauer Committed by Commit Bot

device/fido: fix a crash in IsUVPAA if Touch ID is flag-enabled.

In 9aa7c545
AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailable was
changed to make Touch ID unavailable in Incognito and if the embedder
does not provide a configuration for the Touch ID authenticator. The
latter check dereferenced a nullptr in AuthenticatorImpl's
request_delegate_.  request_delegate_ only gets initialized for the
duration of a MakeCredential or GetAssertion request. It is
uninitialized during IsUVPAA.

This works around the issue by adding a
IsWebAuthenticationTouchIdAuthenticatorSupported instance method to
ContentBrowserClient, so that the feature support can be checked without
requiring a request delegate instance.

Bug: 869651
Change-Id: Ib64a2278d63047d68876e224d44a9aab96f9cfea
Reviewed-on: https://chromium-review.googlesource.com/1157605Reviewed-by: default avatarAlex Moshchuk <alexmos@chromium.org>
Reviewed-by: default avatarKim Paulhamus <kpaulhamus@chromium.org>
Commit-Queue: Martin Kreichgauer <martinkr@google.com>
Cr-Commit-Position: refs/heads/master@{#580014}
parent 704c6174
......@@ -4532,6 +4532,13 @@ ChromeContentBrowserClient::GetWebAuthenticationRequestDelegate(
render_frame_host);
}
#if defined(OS_MACOSX)
bool ChromeContentBrowserClient::
IsWebAuthenticationTouchIdAuthenticatorSupported() {
return true;
}
#endif
std::unique_ptr<net::ClientCertStore>
ChromeContentBrowserClient::CreateClientCertStore(
content::ResourceContext* resource_context) {
......
......@@ -457,6 +457,9 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient {
std::unique_ptr<content::AuthenticatorRequestClientDelegate>
GetWebAuthenticationRequestDelegate(
content::RenderFrameHost* render_frame_host) override;
#if defined(OS_MACOSX)
bool IsWebAuthenticationTouchIdAuthenticatorSupported() override;
#endif
std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
content::ResourceContext* resource_context) override;
scoped_refptr<content::LoginDelegate> CreateLoginDelegate(
......
......@@ -608,15 +608,17 @@ void AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailable(
bool AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailableImpl() {
#if defined(OS_MACOSX)
if (browser_context()->IsOffTheRecord()) {
// Touch ID is disabled, regardless of hardware support, if the embedder
// doesn't support it or if this is an Incognito session. N.B.
// request_delegate_ may be nullptr at this point.
if (!GetContentClient()
->browser()
->IsWebAuthenticationTouchIdAuthenticatorSupported() ||
browser_context()->IsOffTheRecord()) {
return false;
}
// Check whether Touch ID is supported by the hardware and enrolled in the
// OS. Also check whether the (embedder-specific) request delegate provides a
// Touch ID authenticator config.
return device::fido::mac::TouchIdAuthenticator::IsAvailable() &&
request_delegate_->GetTouchIdAuthenticatorConfig();
return device::fido::mac::TouchIdAuthenticator::IsAvailable();
#else
return false;
#endif
......
......@@ -18,6 +18,7 @@
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/cbor/cbor_reader.h"
#include "components/cbor/cbor_values.h"
#include "content/public/browser/authenticator_request_client_delegate.h"
......@@ -195,6 +196,7 @@ constexpr OriginClaimedAuthorityPair kInvalidRelyingPartyTestCases[] = {
{"https://com", "https://www.gstatic.com/securitykey/origins.json"},
};
using TestIsUvpaaCallback = device::test::ValueCallbackReceiver<bool>;
using TestMakeCredentialCallback = device::test::StatusAndValueCallbackReceiver<
AuthenticatorStatus,
MakeCredentialAuthenticatorResponsePtr>;
......@@ -1102,6 +1104,14 @@ class TestAuthenticatorContentBrowserClient : public ContentBrowserClient {
individual_attestation, attestation_consent, is_focused);
}
#if defined(OS_MACOSX)
bool IsWebAuthenticationTouchIdAuthenticatorSupported() override {
return supports_touch_id;
}
bool supports_touch_id = true;
#endif
// If set, this closure will be called when the subsequently constructed
// delegate is informed that the request has started.
base::OnceClosure request_started_callback;
......@@ -1496,6 +1506,20 @@ TEST_F(AuthenticatorContentBrowserClientTest,
}
}
#if defined(OS_MACOSX)
TEST_F(AuthenticatorContentBrowserClientTest, IsUVPAAFalseWithoutTouchId) {
test_client_.supports_touch_id = false;
NavigateAndCommit(GURL(kTestOrigin1));
AuthenticatorPtr authenticator = ConnectToAuthenticator();
TestIsUvpaaCallback cb;
authenticator->IsUserVerifyingPlatformAuthenticatorAvailable(cb.callback());
cb.WaitForCallback();
EXPECT_FALSE(cb.value());
}
#endif
class MockAuthenticatorRequestDelegateObserver
: public TestAuthenticatorRequestDelegate {
public:
......
......@@ -741,6 +741,12 @@ ContentBrowserClient::GetWebAuthenticationRequestDelegate(
return std::make_unique<AuthenticatorRequestClientDelegate>();
}
#if defined(OS_MACOSX)
bool ContentBrowserClient::IsWebAuthenticationTouchIdAuthenticatorSupported() {
return false;
}
#endif
std::unique_ptr<net::ClientCertStore>
ContentBrowserClient::CreateClientCertStore(ResourceContext* resource_context) {
return nullptr;
......
......@@ -1233,6 +1233,13 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual std::unique_ptr<AuthenticatorRequestClientDelegate>
GetWebAuthenticationRequestDelegate(RenderFrameHost* render_frame_host);
#if defined(OS_MACOSX)
// Returns whether WebAuthn supports the built-in Touch ID platform
// authenticator. If true, the embedder must supply a configuration in
// |AuthenticatorRequestClientDelegate::GetTouchIdAuthenticatorConfig|.
virtual bool IsWebAuthenticationTouchIdAuthenticatorSupported();
#endif
// Get platform ClientCertStore. May return nullptr.
virtual std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
ResourceContext* resource_context);
......
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