Include all dupe types (event when value is zero) in scan stats.
[chromium-blink-merge.git] / chromeos / network / client_cert_resolver_unittest.cc
blobfb04d94dc227fa10f32b2396763f69820f4d1c10
1 // Copyright 2013 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 #include "chromeos/network/client_cert_resolver.h"
6 #include <cert.h>
7 #include <pk11pub.h>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/json/json_reader.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/run_loop.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/values.h"
18 #include "chromeos/cert_loader.h"
19 #include "chromeos/dbus/dbus_thread_manager.h"
20 #include "chromeos/dbus/shill_manager_client.h"
21 #include "chromeos/dbus/shill_profile_client.h"
22 #include "chromeos/dbus/shill_service_client.h"
23 #include "chromeos/network/managed_network_configuration_handler_impl.h"
24 #include "chromeos/network/network_configuration_handler.h"
25 #include "chromeos/network/network_profile_handler.h"
26 #include "chromeos/network/network_state_handler.h"
27 #include "components/onc/onc_constants.h"
28 #include "crypto/scoped_nss_types.h"
29 #include "crypto/scoped_test_nss_db.h"
30 #include "net/base/net_errors.h"
31 #include "net/base/test_data_directory.h"
32 #include "net/cert/nss_cert_database_chromeos.h"
33 #include "net/cert/x509_certificate.h"
34 #include "net/test/cert_test_util.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36 #include "third_party/cros_system_api/dbus/service_constants.h"
38 namespace chromeos {
40 namespace {
42 const char* kWifiStub = "wifi_stub";
43 const char* kWifiSSID = "wifi_ssid";
44 const char* kUserProfilePath = "user_profile";
45 const char* kUserHash = "user_hash";
47 } // namespace
49 class ClientCertResolverTest : public testing::Test,
50 public ClientCertResolver::Observer {
51 public:
52 ClientCertResolverTest()
53 : network_properties_changed_count_(0),
54 service_test_(NULL),
55 profile_test_(NULL),
56 cert_loader_(NULL) {}
57 ~ClientCertResolverTest() override {}
59 void SetUp() override {
60 ASSERT_TRUE(test_nssdb_.is_open());
62 // Use the same DB for public and private slot.
63 test_nsscertdb_.reset(new net::NSSCertDatabaseChromeOS(
64 crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot())),
65 crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot()))));
66 test_nsscertdb_->SetSlowTaskRunnerForTest(
67 message_loop_.message_loop_proxy());
69 DBusThreadManager::Initialize();
70 service_test_ =
71 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
72 profile_test_ =
73 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface();
74 profile_test_->AddProfile(kUserProfilePath, kUserHash);
75 base::RunLoop().RunUntilIdle();
76 service_test_->ClearServices();
77 base::RunLoop().RunUntilIdle();
79 CertLoader::Initialize();
80 cert_loader_ = CertLoader::Get();
81 CertLoader::ForceHardwareBackedForTesting();
84 void TearDown() override {
85 client_cert_resolver_->RemoveObserver(this);
86 client_cert_resolver_.reset();
87 managed_config_handler_.reset();
88 network_config_handler_.reset();
89 network_profile_handler_.reset();
90 network_state_handler_.reset();
91 CertLoader::Shutdown();
92 DBusThreadManager::Shutdown();
95 protected:
96 void StartCertLoader() {
97 cert_loader_->StartWithNSSDB(test_nsscertdb_.get());
98 if (test_client_cert_.get()) {
99 int slot_id = 0;
100 const std::string pkcs11_id =
101 CertLoader::GetPkcs11IdAndSlotForCert(*test_client_cert_, &slot_id);
102 test_cert_id_ = base::StringPrintf("%i:%s", slot_id, pkcs11_id.c_str());
106 // Imports a CA cert (stored as PEM in test_ca_cert_pem_) and a client
107 // certificate signed by that CA. Its PKCS#11 ID is stored in
108 // |test_cert_id_|.
109 void SetupTestCerts() {
110 // Import a CA cert.
111 net::CertificateList ca_cert_list =
112 net::CreateCertificateListFromFile(net::GetTestCertsDirectory(),
113 "client_1_ca.pem",
114 net::X509Certificate::FORMAT_AUTO);
115 ASSERT_TRUE(!ca_cert_list.empty());
116 net::NSSCertDatabase::ImportCertFailureList failures;
117 EXPECT_TRUE(test_nsscertdb_->ImportCACerts(
118 ca_cert_list, net::NSSCertDatabase::TRUST_DEFAULT, &failures));
119 ASSERT_TRUE(failures.empty()) << net::ErrorToString(failures[0].net_error);
121 net::X509Certificate::GetPEMEncoded(ca_cert_list[0]->os_cert_handle(),
122 &test_ca_cert_pem_);
123 ASSERT_TRUE(!test_ca_cert_pem_.empty());
125 // Import a client cert signed by that CA.
126 test_client_cert_ =
127 net::ImportClientCertAndKeyFromFile(net::GetTestCertsDirectory(),
128 "client_1.pem",
129 "client_1.pk8",
130 test_nssdb_.slot());
131 ASSERT_TRUE(test_client_cert_.get());
134 void SetupNetworkHandlers() {
135 network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
136 network_profile_handler_.reset(new NetworkProfileHandler());
137 network_config_handler_.reset(new NetworkConfigurationHandler());
138 managed_config_handler_.reset(new ManagedNetworkConfigurationHandlerImpl());
139 client_cert_resolver_.reset(new ClientCertResolver());
141 network_profile_handler_->Init();
142 network_config_handler_->Init(network_state_handler_.get(),
143 NULL /* network_device_handler */);
144 managed_config_handler_->Init(network_state_handler_.get(),
145 network_profile_handler_.get(),
146 network_config_handler_.get(),
147 NULL /* network_device_handler */);
148 // Run all notifications before starting the cert loader to reduce run time.
149 base::RunLoop().RunUntilIdle();
151 client_cert_resolver_->Init(network_state_handler_.get(),
152 managed_config_handler_.get());
153 client_cert_resolver_->AddObserver(this);
154 client_cert_resolver_->SetSlowTaskRunnerForTest(
155 message_loop_.message_loop_proxy());
158 void SetupWifi() {
159 service_test_->SetServiceProperties(kWifiStub,
160 kWifiStub,
161 kWifiSSID,
162 shill::kTypeWifi,
163 shill::kStateOnline,
164 true /* visible */);
165 // Set an arbitrary cert id, so that we can check afterwards whether we
166 // cleared the property or not.
167 service_test_->SetServiceProperty(
168 kWifiStub, shill::kEapCertIdProperty, base::StringValue("invalid id"));
169 profile_test_->AddService(kUserProfilePath, kWifiStub);
171 DBusThreadManager::Get()
172 ->GetShillManagerClient()
173 ->GetTestInterface()
174 ->AddManagerService(kWifiStub, true);
177 // Setup a policy with a certificate pattern that matches any client cert that
178 // is signed by the test CA cert (stored in |test_ca_cert_pem_|). In
179 // particular it will match the test client cert.
180 void SetupPolicy() {
181 const char* kTestPolicyTemplate =
182 "[ { \"GUID\": \"wifi_stub\","
183 " \"Name\": \"wifi_stub\","
184 " \"Type\": \"WiFi\","
185 " \"WiFi\": {"
186 " \"Security\": \"WPA-EAP\","
187 " \"SSID\": \"wifi_ssid\","
188 " \"EAP\": {"
189 " \"Outer\": \"EAP-TLS\","
190 " \"ClientCertType\": \"Pattern\","
191 " \"ClientCertPattern\": {"
192 " \"IssuerCAPEMs\": [ \"%s\" ]"
193 " }"
194 " }"
195 " }"
196 "} ]";
197 std::string policy_json =
198 base::StringPrintf(kTestPolicyTemplate, test_ca_cert_pem_.c_str());
200 std::string error;
201 scoped_ptr<base::Value> policy_value(
202 base::JSONReader::DeprecatedReadAndReturnError(
203 policy_json, base::JSON_ALLOW_TRAILING_COMMAS, NULL, &error));
204 ASSERT_TRUE(policy_value) << error;
206 base::ListValue* policy = NULL;
207 ASSERT_TRUE(policy_value->GetAsList(&policy));
209 managed_config_handler_->SetPolicy(
210 onc::ONC_SOURCE_USER_POLICY,
211 kUserHash,
212 *policy,
213 base::DictionaryValue() /* no global network config */);
216 void GetClientCertProperties(std::string* pkcs11_id) {
217 pkcs11_id->clear();
218 const base::DictionaryValue* properties =
219 service_test_->GetServiceProperties(kWifiStub);
220 if (!properties)
221 return;
222 properties->GetStringWithoutPathExpansion(shill::kEapCertIdProperty,
223 pkcs11_id);
226 int network_properties_changed_count_;
227 std::string test_cert_id_;
228 scoped_ptr<ClientCertResolver> client_cert_resolver_;
230 private:
231 // ClientCertResolver::Observer:
232 void ResolveRequestCompleted(bool network_properties_changed) override {
233 if (network_properties_changed)
234 ++network_properties_changed_count_;
237 ShillServiceClient::TestInterface* service_test_;
238 ShillProfileClient::TestInterface* profile_test_;
239 CertLoader* cert_loader_;
240 scoped_ptr<NetworkStateHandler> network_state_handler_;
241 scoped_ptr<NetworkProfileHandler> network_profile_handler_;
242 scoped_ptr<NetworkConfigurationHandler> network_config_handler_;
243 scoped_ptr<ManagedNetworkConfigurationHandlerImpl> managed_config_handler_;
244 base::MessageLoop message_loop_;
245 scoped_refptr<net::X509Certificate> test_client_cert_;
246 std::string test_ca_cert_pem_;
247 crypto::ScopedTestNSSDB test_nssdb_;
248 scoped_ptr<net::NSSCertDatabaseChromeOS> test_nsscertdb_;
250 DISALLOW_COPY_AND_ASSIGN(ClientCertResolverTest);
253 TEST_F(ClientCertResolverTest, NoMatchingCertificates) {
254 StartCertLoader();
255 SetupWifi();
256 base::RunLoop().RunUntilIdle();
257 network_properties_changed_count_ = 0;
258 SetupNetworkHandlers();
259 SetupPolicy();
260 base::RunLoop().RunUntilIdle();
262 // Verify that no client certificate was configured.
263 std::string pkcs11_id;
264 GetClientCertProperties(&pkcs11_id);
265 EXPECT_EQ(std::string(), pkcs11_id);
266 EXPECT_EQ(1, network_properties_changed_count_);
267 EXPECT_FALSE(client_cert_resolver_->IsAnyResolveTaskRunning());
270 TEST_F(ClientCertResolverTest, ResolveOnCertificatesLoaded) {
271 SetupTestCerts();
272 SetupWifi();
273 base::RunLoop().RunUntilIdle();
275 SetupNetworkHandlers();
276 SetupPolicy();
277 base::RunLoop().RunUntilIdle();
279 network_properties_changed_count_ = 0;
280 StartCertLoader();
281 base::RunLoop().RunUntilIdle();
283 // Verify that the resolver positively matched the pattern in the policy with
284 // the test client cert and configured the network.
285 std::string pkcs11_id;
286 GetClientCertProperties(&pkcs11_id);
287 EXPECT_EQ(test_cert_id_, pkcs11_id);
288 EXPECT_EQ(1, network_properties_changed_count_);
291 TEST_F(ClientCertResolverTest, ResolveAfterPolicyApplication) {
292 SetupTestCerts();
293 SetupWifi();
294 base::RunLoop().RunUntilIdle();
295 StartCertLoader();
296 SetupNetworkHandlers();
297 base::RunLoop().RunUntilIdle();
299 // Policy application will trigger the ClientCertResolver.
300 network_properties_changed_count_ = 0;
301 SetupPolicy();
302 base::RunLoop().RunUntilIdle();
304 // Verify that the resolver positively matched the pattern in the policy with
305 // the test client cert and configured the network.
306 std::string pkcs11_id;
307 GetClientCertProperties(&pkcs11_id);
308 EXPECT_EQ(test_cert_id_, pkcs11_id);
309 EXPECT_EQ(1, network_properties_changed_count_);
312 } // namespace chromeos