1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/browser/webauth/virtual_fido_discovery_factory.h"
6 
7 #include <utility>
8 #include <vector>
9 
10 #include "base/command_line.h"
11 #include "base/stl_util.h"
12 #include "content/browser/webauth/virtual_authenticator.h"
13 #include "content/browser/webauth/virtual_discovery.h"
14 #include "content/public/common/content_switches.h"
15 #include "device/fido/fido_discovery_base.h"
16 #include "device/fido/virtual_ctap2_device.h"
17 #include "device/fido/virtual_u2f_device.h"
18 #include "mojo/public/cpp/bindings/pending_remote.h"
19 
20 namespace content {
21 
22 namespace {
23 
24 mojo::PendingRemote<blink::test::mojom::VirtualAuthenticator>
GetMojoToVirtualAuthenticator(VirtualAuthenticator * authenticator)25 GetMojoToVirtualAuthenticator(VirtualAuthenticator* authenticator) {
26   mojo::PendingRemote<blink::test::mojom::VirtualAuthenticator>
27       mojo_authenticator;
28   authenticator->AddReceiver(
29       mojo_authenticator.InitWithNewPipeAndPassReceiver());
30   return mojo_authenticator;
31 }
32 
33 }  // namespace
34 
VirtualFidoDiscoveryFactory()35 VirtualFidoDiscoveryFactory::VirtualFidoDiscoveryFactory()
36     : virtual_device_state_(new device::VirtualFidoDevice::State) {}
37 
38 VirtualFidoDiscoveryFactory::~VirtualFidoDiscoveryFactory() = default;
39 
CreateAuthenticator(device::ProtocolVersion protocol,device::FidoTransportProtocol transport,device::AuthenticatorAttachment attachment,bool has_resident_key,bool has_user_verification)40 VirtualAuthenticator* VirtualFidoDiscoveryFactory::CreateAuthenticator(
41     device::ProtocolVersion protocol,
42     device::FidoTransportProtocol transport,
43     device::AuthenticatorAttachment attachment,
44     bool has_resident_key,
45     bool has_user_verification) {
46   if (protocol == device::ProtocolVersion::kU2f &&
47       !device::VirtualU2fDevice::IsTransportSupported(transport)) {
48     return nullptr;
49   }
50   auto authenticator = std::make_unique<VirtualAuthenticator>(
51       protocol, transport, attachment, has_resident_key, has_user_verification);
52   auto* authenticator_ptr = authenticator.get();
53   authenticators_.emplace(authenticator_ptr->unique_id(),
54                           std::move(authenticator));
55 
56   for (auto* discovery : discoveries_) {
57     if (discovery->transport() != authenticator_ptr->transport())
58       continue;
59     discovery->AddVirtualDevice(authenticator_ptr->ConstructDevice());
60   }
61   return authenticator_ptr;
62 }
63 
GetAuthenticator(const std::string & id)64 VirtualAuthenticator* VirtualFidoDiscoveryFactory::GetAuthenticator(
65     const std::string& id) {
66   auto authenticator = authenticators_.find(id);
67   if (authenticator == authenticators_.end())
68     return nullptr;
69   return authenticator->second.get();
70 }
71 
72 std::vector<VirtualAuthenticator*>
GetAuthenticators()73 VirtualFidoDiscoveryFactory::GetAuthenticators() {
74   std::vector<VirtualAuthenticator*> authenticators;
75   for (auto& authenticator : authenticators_)
76     authenticators.push_back(authenticator.second.get());
77   return authenticators;
78 }
79 
RemoveAuthenticator(const std::string & id)80 bool VirtualFidoDiscoveryFactory::RemoveAuthenticator(const std::string& id) {
81   const bool removed = authenticators_.erase(id);
82   if (removed) {
83     for (auto* discovery : discoveries_)
84       discovery->RemoveVirtualDevice(id);
85   }
86 
87   return removed;
88 }
89 
AddReceiver(mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticatorManager> receiver)90 void VirtualFidoDiscoveryFactory::AddReceiver(
91     mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticatorManager>
92         receiver) {
93   receivers_.Add(this, std::move(receiver));
94 }
95 
OnDiscoveryDestroyed(VirtualFidoDiscovery * discovery)96 void VirtualFidoDiscoveryFactory::OnDiscoveryDestroyed(
97     VirtualFidoDiscovery* discovery) {
98   if (base::Contains(discoveries_, discovery))
99     discoveries_.erase(discovery);
100 }
101 
102 std::unique_ptr<::device::FidoDiscoveryBase>
Create(device::FidoTransportProtocol transport)103 VirtualFidoDiscoveryFactory::Create(device::FidoTransportProtocol transport) {
104   auto discovery = std::make_unique<VirtualFidoDiscovery>(transport);
105 
106   for (auto& authenticator : authenticators_) {
107     if (discovery->transport() != authenticator.second->transport())
108       continue;
109     discovery->AddVirtualDevice(authenticator.second->ConstructDevice());
110   }
111 
112   discoveries_.insert(discovery.get());
113   return discovery;
114 }
115 
CreateAuthenticator(blink::test::mojom::VirtualAuthenticatorOptionsPtr options,CreateAuthenticatorCallback callback)116 void VirtualFidoDiscoveryFactory::CreateAuthenticator(
117     blink::test::mojom::VirtualAuthenticatorOptionsPtr options,
118     CreateAuthenticatorCallback callback) {
119   auto* authenticator = CreateAuthenticator(
120       options->protocol, options->transport, options->attachment,
121       options->has_resident_key, options->has_user_verification);
122   authenticator->SetUserPresence(options->is_user_present);
123 
124   std::move(callback).Run(GetMojoToVirtualAuthenticator(authenticator));
125 }
126 
GetAuthenticators(GetAuthenticatorsCallback callback)127 void VirtualFidoDiscoveryFactory::GetAuthenticators(
128     GetAuthenticatorsCallback callback) {
129   std::vector<mojo::PendingRemote<blink::test::mojom::VirtualAuthenticator>>
130       mojo_authenticators;
131   for (auto& authenticator : authenticators_) {
132     mojo_authenticators.push_back(
133         GetMojoToVirtualAuthenticator(authenticator.second.get()));
134   }
135 
136   std::move(callback).Run(std::move(mojo_authenticators));
137 }
138 
RemoveAuthenticator(const std::string & id,RemoveAuthenticatorCallback callback)139 void VirtualFidoDiscoveryFactory::RemoveAuthenticator(
140     const std::string& id,
141     RemoveAuthenticatorCallback callback) {
142   std::move(callback).Run(RemoveAuthenticator(id));
143 }
144 
ClearAuthenticators(ClearAuthenticatorsCallback callback)145 void VirtualFidoDiscoveryFactory::ClearAuthenticators(
146     ClearAuthenticatorsCallback callback) {
147   for (auto& authenticator : authenticators_) {
148     for (auto* discovery : discoveries_) {
149       discovery->RemoveVirtualDevice(authenticator.second->unique_id());
150     }
151   }
152   authenticators_.clear();
153 
154   std::move(callback).Run();
155 }
156 
157 }  // namespace content
158