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( ...@@ -4532,6 +4532,13 @@ ChromeContentBrowserClient::GetWebAuthenticationRequestDelegate(
render_frame_host); render_frame_host);
} }
#if defined(OS_MACOSX)
bool ChromeContentBrowserClient::
IsWebAuthenticationTouchIdAuthenticatorSupported() {
return true;
}
#endif
std::unique_ptr<net::ClientCertStore> std::unique_ptr<net::ClientCertStore>
ChromeContentBrowserClient::CreateClientCertStore( ChromeContentBrowserClient::CreateClientCertStore(
content::ResourceContext* resource_context) { content::ResourceContext* resource_context) {
......
...@@ -457,6 +457,9 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient { ...@@ -457,6 +457,9 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient {
std::unique_ptr<content::AuthenticatorRequestClientDelegate> std::unique_ptr<content::AuthenticatorRequestClientDelegate>
GetWebAuthenticationRequestDelegate( GetWebAuthenticationRequestDelegate(
content::RenderFrameHost* render_frame_host) override; content::RenderFrameHost* render_frame_host) override;
#if defined(OS_MACOSX)
bool IsWebAuthenticationTouchIdAuthenticatorSupported() override;
#endif
std::unique_ptr<net::ClientCertStore> CreateClientCertStore( std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
content::ResourceContext* resource_context) override; content::ResourceContext* resource_context) override;
scoped_refptr<content::LoginDelegate> CreateLoginDelegate( scoped_refptr<content::LoginDelegate> CreateLoginDelegate(
......
...@@ -608,15 +608,17 @@ void AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailable( ...@@ -608,15 +608,17 @@ void AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailable(
bool AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailableImpl() { bool AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailableImpl() {
#if defined(OS_MACOSX) #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; return false;
} }
// Check whether Touch ID is supported by the hardware and enrolled in the return device::fido::mac::TouchIdAuthenticator::IsAvailable();
// OS. Also check whether the (embedder-specific) request delegate provides a
// Touch ID authenticator config.
return device::fido::mac::TouchIdAuthenticator::IsAvailable() &&
request_delegate_->GetTouchIdAuthenticatorConfig();
#else #else
return false; return false;
#endif #endif
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "base/test/test_mock_time_task_runner.h" #include "base/test/test_mock_time_task_runner.h"
#include "base/time/tick_clock.h" #include "base/time/tick_clock.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h"
#include "components/cbor/cbor_reader.h" #include "components/cbor/cbor_reader.h"
#include "components/cbor/cbor_values.h" #include "components/cbor/cbor_values.h"
#include "content/public/browser/authenticator_request_client_delegate.h" #include "content/public/browser/authenticator_request_client_delegate.h"
...@@ -195,6 +196,7 @@ constexpr OriginClaimedAuthorityPair kInvalidRelyingPartyTestCases[] = { ...@@ -195,6 +196,7 @@ constexpr OriginClaimedAuthorityPair kInvalidRelyingPartyTestCases[] = {
{"https://com", "https://www.gstatic.com/securitykey/origins.json"}, {"https://com", "https://www.gstatic.com/securitykey/origins.json"},
}; };
using TestIsUvpaaCallback = device::test::ValueCallbackReceiver<bool>;
using TestMakeCredentialCallback = device::test::StatusAndValueCallbackReceiver< using TestMakeCredentialCallback = device::test::StatusAndValueCallbackReceiver<
AuthenticatorStatus, AuthenticatorStatus,
MakeCredentialAuthenticatorResponsePtr>; MakeCredentialAuthenticatorResponsePtr>;
...@@ -1102,6 +1104,14 @@ class TestAuthenticatorContentBrowserClient : public ContentBrowserClient { ...@@ -1102,6 +1104,14 @@ class TestAuthenticatorContentBrowserClient : public ContentBrowserClient {
individual_attestation, attestation_consent, is_focused); 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 // If set, this closure will be called when the subsequently constructed
// delegate is informed that the request has started. // delegate is informed that the request has started.
base::OnceClosure request_started_callback; base::OnceClosure request_started_callback;
...@@ -1496,6 +1506,20 @@ TEST_F(AuthenticatorContentBrowserClientTest, ...@@ -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 class MockAuthenticatorRequestDelegateObserver
: public TestAuthenticatorRequestDelegate { : public TestAuthenticatorRequestDelegate {
public: public:
......
...@@ -741,6 +741,12 @@ ContentBrowserClient::GetWebAuthenticationRequestDelegate( ...@@ -741,6 +741,12 @@ ContentBrowserClient::GetWebAuthenticationRequestDelegate(
return std::make_unique<AuthenticatorRequestClientDelegate>(); return std::make_unique<AuthenticatorRequestClientDelegate>();
} }
#if defined(OS_MACOSX)
bool ContentBrowserClient::IsWebAuthenticationTouchIdAuthenticatorSupported() {
return false;
}
#endif
std::unique_ptr<net::ClientCertStore> std::unique_ptr<net::ClientCertStore>
ContentBrowserClient::CreateClientCertStore(ResourceContext* resource_context) { ContentBrowserClient::CreateClientCertStore(ResourceContext* resource_context) {
return nullptr; return nullptr;
......
...@@ -1233,6 +1233,13 @@ class CONTENT_EXPORT ContentBrowserClient { ...@@ -1233,6 +1233,13 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual std::unique_ptr<AuthenticatorRequestClientDelegate> virtual std::unique_ptr<AuthenticatorRequestClientDelegate>
GetWebAuthenticationRequestDelegate(RenderFrameHost* render_frame_host); 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. // Get platform ClientCertStore. May return nullptr.
virtual std::unique_ptr<net::ClientCertStore> CreateClientCertStore( virtual std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
ResourceContext* resource_context); 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