blob: ae495ff96a19e896f9e3f0dd225b44a789f99f03 [file] [log] [blame]
[email protected]72b3a7e2013-08-13 15:30:041// 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"
5
6#include <cert.h>
7#include <pk11pub.h>
8
dcheng0a6e80c2016-04-08 18:37:389#include <memory>
10
Pavol Marko0b3fedd2018-10-29 11:57:2011#include "base/base64.h"
pneubeckf501c652014-11-05 21:03:5712#include "base/bind.h"
13#include "base/bind_helpers.h"
Pavol Marko0b3fedd2018-10-29 11:57:2014#include "base/callback_helpers.h"
[email protected]72b3a7e2013-08-13 15:30:0415#include "base/files/file_path.h"
thestigb44bd352014-09-10 01:47:0616#include "base/files/file_util.h"
[email protected]72b3a7e2013-08-13 15:30:0417#include "base/json/json_reader.h"
avi6e1a22d2015-12-21 03:43:2018#include "base/macros.h"
Pavol Marko0b3fedd2018-10-29 11:57:2019#include "base/run_loop.h"
[email protected]72b3a7e2013-08-13 15:30:0420#include "base/strings/stringprintf.h"
Francois Dorayef354392017-07-28 15:18:0221#include "base/test/scoped_task_environment.h"
emaxx98181cd2015-11-17 18:08:1222#include "base/test/simple_test_clock.h"
[email protected]e5ed56eb2013-10-21 21:07:5323#include "base/values.h"
Steven Bennettsb4bf6cd2019-04-05 17:02:5724#include "chromeos/dbus/shill/shill_clients.h"
Steven Bennettsd11e440f2019-04-04 01:09:0025#include "chromeos/dbus/shill/shill_manager_client.h"
26#include "chromeos/dbus/shill/shill_profile_client.h"
27#include "chromeos/dbus/shill/shill_service_client.h"
[email protected]1b4d5fc2013-08-19 22:35:0728#include "chromeos/network/managed_network_configuration_handler_impl.h"
Pavol Marko5006c4c2018-10-09 12:58:1029#include "chromeos/network/network_cert_loader.h"
[email protected]72b3a7e2013-08-13 15:30:0430#include "chromeos/network/network_configuration_handler.h"
31#include "chromeos/network/network_profile_handler.h"
32#include "chromeos/network/network_state_handler.h"
Pavol Marko0b3fedd2018-10-29 11:57:2033#include "chromeos/network/onc/onc_certificate_importer_impl.h"
34#include "chromeos/network/onc/onc_test_utils.h"
[email protected]c72ace842014-05-15 08:47:3235#include "components/onc/onc_constants.h"
pneubeckf501c652014-11-05 21:03:5736#include "crypto/scoped_nss_types.h"
37#include "crypto/scoped_test_nss_db.h"
[email protected]72b3a7e2013-08-13 15:30:0438#include "net/base/net_errors.h"
[email protected]69295ba2014-01-28 06:17:0039#include "net/cert/nss_cert_database_chromeos.h"
Pavol Marko6ce72d02017-12-15 00:34:2440#include "net/cert/pem_tokenizer.h"
[email protected]72b3a7e2013-08-13 15:30:0441#include "net/cert/x509_certificate.h"
Matt Mueller0d0c1422017-09-07 18:08:3842#include "net/cert/x509_util_nss.h"
[email protected]72b3a7e2013-08-13 15:30:0443#include "net/test/cert_test_util.h"
rsleevia69c79a2016-06-22 03:28:4344#include "net/test/test_data_directory.h"
[email protected]72b3a7e2013-08-13 15:30:0445#include "testing/gtest/include/gtest/gtest.h"
46#include "third_party/cros_system_api/dbus/service_constants.h"
47
48namespace chromeos {
49
50namespace {
51
Pavol Marko6ce72d02017-12-15 00:34:2452constexpr char kWifiStub[] = "wifi_stub";
53constexpr char kWifiSSID[] = "wifi_ssid";
54constexpr char kUserProfilePath[] = "user_profile";
55constexpr char kUserHash[] = "user_hash";
[email protected]72b3a7e2013-08-13 15:30:0456
Pavol Marko0b3fedd2018-10-29 11:57:2057void OnImportCompleted(base::OnceClosure loop_quit_closure, bool success) {
58 EXPECT_TRUE(success);
59 std::move(loop_quit_closure).Run();
60}
61
62void OnListCertsDone(base::OnceClosure loop_quit_closure,
63 net::ScopedCERTCertificateList* out_cert_list,
64 net::ScopedCERTCertificateList cert_list) {
65 out_cert_list->swap(cert_list);
66 std::move(loop_quit_closure).Run();
67}
68
69// Returns a |OncParsedCertificates| which contains exactly one client
70// certificate with the contents of |client_cert_pkcs12_file| and the GUID
71// |guid|. Returns nullptr if the file could not be read.
72std::unique_ptr<onc::OncParsedCertificates> OncParsedCertificatesForPkcs12File(
73 const base::FilePath& client_cert_pkcs12_file,
74 base::StringPiece guid) {
75 std::string pkcs12_raw;
76 if (!base::ReadFileToString(client_cert_pkcs12_file, &pkcs12_raw))
77 return nullptr;
78
79 std::string pkcs12_base64_encoded;
80 base::Base64Encode(pkcs12_raw, &pkcs12_base64_encoded);
81
82 base::Value onc_certificate(base::Value::Type::DICTIONARY);
83 onc_certificate.SetKey("GUID", base::Value(guid));
84 onc_certificate.SetKey("Type", base::Value("Client"));
85 onc_certificate.SetKey("PKCS12", base::Value(pkcs12_base64_encoded));
86 base::Value onc_certificates(base::Value::Type::LIST);
87 onc_certificates.GetList().push_back(std::move(onc_certificate));
88 return std::make_unique<onc::OncParsedCertificates>(onc_certificates);
89}
90
[email protected]72b3a7e2013-08-13 15:30:0491} // namespace
92
pneubeckf501c652014-11-05 21:03:5793class ClientCertResolverTest : public testing::Test,
94 public ClientCertResolver::Observer {
[email protected]72b3a7e2013-08-13 15:30:0495 public:
Chris Watkins2c529d62017-11-29 02:14:4196 ClientCertResolverTest() = default;
97 ~ClientCertResolverTest() override = default;
[email protected]72b3a7e2013-08-13 15:30:0498
pneubeckf501c652014-11-05 21:03:5799 void SetUp() override {
100 ASSERT_TRUE(test_nssdb_.is_open());
pmarko93bc5d72017-04-27 10:58:28101 ASSERT_TRUE(test_system_nssdb_.is_open());
Pavol Markoa835cfa2019-02-18 12:38:34102 // Use the same slot as public and private slot for the user's
103 // NSSCertDatabse for testing.
104 test_nsscertdb_ = std::make_unique<net::NSSCertDatabaseChromeOS>(
pneubeckf501c652014-11-05 21:03:57105 crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot())),
Pavol Markoa835cfa2019-02-18 12:38:34106 crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot())));
107 // Create a NSSCertDatabase for the system slot. While NetworkCertLoader
108 // does not care about the public slot in this database, NSSCertDatabase
109 // requires a public slot. Pass the system slot there for testing.
110 test_system_nsscertdb_ = std::make_unique<net::NSSCertDatabaseChromeOS>(
111 crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_system_nssdb_.slot())),
112 crypto::ScopedPK11Slot() /* private_slot */);
113 test_system_nsscertdb_->SetSystemSlot(
114 crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_system_nssdb_.slot())));
[email protected]72b3a7e2013-08-13 15:30:04115
Steven Bennettsb4bf6cd2019-04-05 17:02:57116 shill_clients::InitializeFakes();
117 service_test_ = ShillServiceClient::Get()->GetTestInterface();
118 profile_test_ = ShillProfileClient::Get()->GetTestInterface();
pneubeckd0f72112014-10-24 13:30:00119 profile_test_->AddProfile(kUserProfilePath, kUserHash);
Gabriel Charette694c3c332019-08-19 14:53:05120 task_environment_.RunUntilIdle();
[email protected]72b3a7e2013-08-13 15:30:04121 service_test_->ClearServices();
Gabriel Charette694c3c332019-08-19 14:53:05122 task_environment_.RunUntilIdle();
[email protected]72b3a7e2013-08-13 15:30:04123
Pavol Marko5006c4c2018-10-09 12:58:10124 NetworkCertLoader::Initialize();
125 network_cert_loader_ = NetworkCertLoader::Get();
126 NetworkCertLoader::ForceHardwareBackedForTesting();
[email protected]72b3a7e2013-08-13 15:30:04127 }
128
pneubeckf501c652014-11-05 21:03:57129 void TearDown() override {
pmarko93bc5d72017-04-27 10:58:28130 if (client_cert_resolver_)
131 client_cert_resolver_->RemoveObserver(this);
[email protected]72b3a7e2013-08-13 15:30:04132 client_cert_resolver_.reset();
emaxx98181cd2015-11-17 18:08:12133 test_clock_.reset();
pmarko93bc5d72017-04-27 10:58:28134 if (network_state_handler_)
135 network_state_handler_->Shutdown();
[email protected]72b3a7e2013-08-13 15:30:04136 managed_config_handler_.reset();
137 network_config_handler_.reset();
138 network_profile_handler_.reset();
139 network_state_handler_.reset();
Pavol Marko5006c4c2018-10-09 12:58:10140 NetworkCertLoader::Shutdown();
Steven Bennettsb4bf6cd2019-04-05 17:02:57141 shill_clients::Shutdown();
[email protected]72b3a7e2013-08-13 15:30:04142 }
143
144 protected:
Pavol Marko5006c4c2018-10-09 12:58:10145 void StartNetworkCertLoader() {
146 network_cert_loader_->SetUserNSSDB(test_nsscertdb_.get());
Pavol Markoa835cfa2019-02-18 12:38:34147 network_cert_loader_->SetSystemNSSDB(test_system_nsscertdb_.get());
dcheng5adf8d22014-09-11 00:53:37148 if (test_client_cert_.get()) {
[email protected]5fffe152014-07-30 19:40:09149 int slot_id = 0;
Pavol Marko5006c4c2018-10-09 12:58:10150 const std::string pkcs11_id =
151 NetworkCertLoader::GetPkcs11IdAndSlotForCert(test_client_cert_.get(),
152 &slot_id);
[email protected]5fffe152014-07-30 19:40:09153 test_cert_id_ = base::StringPrintf("%i:%s", slot_id, pkcs11_id.c_str());
[email protected]1e042d72014-07-03 12:09:17154 }
155 }
156
Pavol Marko5006c4c2018-10-09 12:58:10157 // Imports a client certificate. After a subsequent StartNetworkCertLoader()
Pavol Marko6ce72d02017-12-15 00:34:24158 // invocation, the PKCS#11 ID of the imported certificate will be stored in
159 // |test_cert_id_|. If |import_issuer| is true, also imports the CA cert
160 // (stored as PEM in test_ca_cert_pem_) that issued the client certificate.
cernekee969c5122016-03-03 19:28:31161 void SetupTestCerts(const std::string& prefix, bool import_issuer) {
pneubeck908e55b2015-09-30 16:53:49162 // Load a CA cert.
Matt Mueller0d0c1422017-09-07 18:08:38163 net::ScopedCERTCertificateList ca_cert_list =
164 net::CreateCERTCertificateListFromFile(
165 net::GetTestCertsDirectory(), prefix + "_ca.pem",
166 net::X509Certificate::FORMAT_AUTO);
[email protected]72b3a7e2013-08-13 15:30:04167 ASSERT_TRUE(!ca_cert_list.empty());
Matt Mueller0d0c1422017-09-07 18:08:38168 net::x509_util::GetPEMEncoded(ca_cert_list[0].get(), &test_ca_cert_pem_);
[email protected]72b3a7e2013-08-13 15:30:04169 ASSERT_TRUE(!test_ca_cert_pem_.empty());
170
pneubeck908e55b2015-09-30 16:53:49171 if (import_issuer) {
172 net::NSSCertDatabase::ImportCertFailureList failures;
173 EXPECT_TRUE(test_nsscertdb_->ImportCACerts(
174 ca_cert_list, net::NSSCertDatabase::TRUST_DEFAULT, &failures));
175 ASSERT_TRUE(failures.empty())
176 << net::ErrorToString(failures[0].net_error);
177 }
178
[email protected]72b3a7e2013-08-13 15:30:04179 // Import a client cert signed by that CA.
Matt Mueller0d0c1422017-09-07 18:08:38180 net::ImportClientCertAndKeyFromFile(net::GetTestCertsDirectory(),
181 prefix + ".pem", prefix + ".pk8",
182 test_nssdb_.slot(), &test_client_cert_);
pneubeckd0f72112014-10-24 13:30:00183 ASSERT_TRUE(test_client_cert_.get());
[email protected]72b3a7e2013-08-13 15:30:04184 }
185
Pavol Marko6ce72d02017-12-15 00:34:24186 // Imports a client certificate with a subject CommonName encoded as
187 // PrintableString, but containing invalid characters. It is imported into the
Pavol Marko5006c4c2018-10-09 12:58:10188 // user slot. After a subsequent StartNetworkCertLoader() invocation, the
189 // PKCS#11 ID of the imported certificate will be stored in |test_cert_id_|.
Pavol Marko6ce72d02017-12-15 00:34:24190 void SetupTestCertWithBadPrintableString() {
191 base::FilePath certs_dir = net::GetTestNetDataDirectory().AppendASCII(
192 "parse_certificate_unittest");
193 ASSERT_TRUE(net::ImportSensitiveKeyFromFile(
194 certs_dir, "v3_certificate_template.pk8", test_nssdb_.slot()));
195
196 std::string file_data;
197 ASSERT_TRUE(base::ReadFileToString(
198 certs_dir.AppendASCII(
199 "subject_printable_string_containing_utf8_client_cert.pem"),
200 &file_data));
201
202 net::PEMTokenizer pem_tokenizer(file_data, {"CERTIFICATE"});
203 ASSERT_TRUE(pem_tokenizer.GetNext());
204 std::string cert_der(pem_tokenizer.data());
205 ASSERT_FALSE(pem_tokenizer.GetNext());
206
207 test_client_cert_ = net::x509_util::CreateCERTCertificateFromBytes(
208 reinterpret_cast<const uint8_t*>(cert_der.data()), cert_der.size());
209 ASSERT_TRUE(test_client_cert_);
210
211 ASSERT_TRUE(net::ImportClientCertToSlot(test_client_cert_.get(),
212 test_nssdb_.slot()));
213 }
214
pmarko93bc5d72017-04-27 10:58:28215 void SetupTestCertInSystemToken(const std::string& prefix) {
Matt Mueller0d0c1422017-09-07 18:08:38216 net::ImportClientCertAndKeyFromFile(
pmarko93bc5d72017-04-27 10:58:28217 net::GetTestCertsDirectory(), prefix + ".pem", prefix + ".pk8",
Matt Mueller0d0c1422017-09-07 18:08:38218 test_system_nssdb_.slot(), &test_client_cert_);
pmarko93bc5d72017-04-27 10:58:28219 ASSERT_TRUE(test_client_cert_.get());
220 }
221
[email protected]72b3a7e2013-08-13 15:30:04222 void SetupNetworkHandlers() {
thestig1a5f12f02016-11-04 18:46:11223 network_state_handler_ = NetworkStateHandler::InitializeForTest();
[email protected]72b3a7e2013-08-13 15:30:04224 network_profile_handler_.reset(new NetworkProfileHandler());
225 network_config_handler_.reset(new NetworkConfigurationHandler());
[email protected]1b4d5fc2013-08-19 22:35:07226 managed_config_handler_.reset(new ManagedNetworkConfigurationHandlerImpl());
[email protected]72b3a7e2013-08-13 15:30:04227 client_cert_resolver_.reset(new ClientCertResolver());
228
emaxx98181cd2015-11-17 18:08:12229 test_clock_.reset(new base::SimpleTestClock);
230 test_clock_->SetNow(base::Time::Now());
231 client_cert_resolver_->SetClockForTesting(test_clock_.get());
232
[email protected]fa0336f2014-06-12 22:08:38233 network_profile_handler_->Init();
stevenjbd97aaeee2015-01-08 22:40:59234 network_config_handler_->Init(network_state_handler_.get(),
fqjfee5067a2015-11-13 20:12:59235 nullptr /* network_device_handler */);
236 managed_config_handler_->Init(
237 network_state_handler_.get(), network_profile_handler_.get(),
238 network_config_handler_.get(), nullptr /* network_device_handler */,
239 nullptr /* prohibited_technologies_handler */);
pneubeckd0f72112014-10-24 13:30:00240 // Run all notifications before starting the cert loader to reduce run time.
Gabriel Charette694c3c332019-08-19 14:53:05241 task_environment_.RunUntilIdle();
pneubeckd0f72112014-10-24 13:30:00242
[email protected]72b3a7e2013-08-13 15:30:04243 client_cert_resolver_->Init(network_state_handler_.get(),
244 managed_config_handler_.get());
pneubeckf501c652014-11-05 21:03:57245 client_cert_resolver_->AddObserver(this);
[email protected]72b3a7e2013-08-13 15:30:04246 }
247
248 void SetupWifi() {
[email protected]1e042d72014-07-03 12:09:17249 service_test_->SetServiceProperties(kWifiStub,
250 kWifiStub,
251 kWifiSSID,
252 shill::kTypeWifi,
253 shill::kStateOnline,
254 true /* visible */);
255 // Set an arbitrary cert id, so that we can check afterwards whether we
256 // cleared the property or not.
jdoerrie122c4da2017-03-06 11:12:04257 service_test_->SetServiceProperty(kWifiStub, shill::kEapCertIdProperty,
258 base::Value("invalid id"));
[email protected]72b3a7e2013-08-13 15:30:04259 profile_test_->AddService(kUserProfilePath, kWifiStub);
[email protected]1e042d72014-07-03 12:09:17260
Steven Bennettsb4bf6cd2019-04-05 17:02:57261 ShillManagerClient::Get()->GetTestInterface()->AddManagerService(kWifiStub,
262 true);
[email protected]72b3a7e2013-08-13 15:30:04263 }
264
pneubeck908e55b2015-09-30 16:53:49265 // Sets up a policy with a certificate pattern that matches any client cert
Pavol Marko6ce72d02017-12-15 00:34:24266 // with a certain Issuer CN. It will match the test client cert imported by
267 // SetupTestCerts.
Pavol Marko0b3fedd2018-10-29 11:57:20268 void SetupPolicyMatchingIssuerCN(::onc::ONCSource onc_source) {
269 const char* test_policy = R"(
270 [ { "GUID": "wifi_stub",
271 "Name": "wifi_stub",
272 "Type": "WiFi",
273 "WiFi": {
274 "Security": "WPA-EAP",
275 "SSID": "wifi_ssid",
276 "EAP": {
277 "Outer": "EAP-TLS",
278 "ClientCertType": "Pattern",
279 "ClientCertPattern": {
280 "Issuer": {
281 "CommonName": "B CA"
282 }
283 }
284 }
285 }
286 } ])";
287 ASSERT_NO_FATAL_FAILURE(SetManagedNetworkPolicy(onc_source, test_policy));
Pavol Marko6ce72d02017-12-15 00:34:24288 }
289
290 // Sets up a policy with a certificate pattern that matches any client cert
291 // with a Subject Organization set to "Blar". It will match the test client
292 // cert imported by SetupTestCertWithBadPrintableString.
293 void SetupPolicyMatchingSubjectOrgForBadPrintableStringCert(
Pavol Marko0b3fedd2018-10-29 11:57:20294 ::onc::ONCSource onc_source) {
295 const char* test_policy = R"(
296 [ { "GUID": "wifi_stub",
297 "Name": "wifi_stub",
298 "Type": "WiFi",
299 "WiFi": {
300 "Security": "WPA-EAP",
301 "SSID": "wifi_ssid",
302 "EAP": {
303 "Outer": "EAP-TLS",
304 "ClientCertType": "Pattern",
305 "ClientCertPattern": {
306 "Subject": {
307 "Organization": "Blar"
308 }
309 }
310 }
311 }
312 } ])";
313 ASSERT_NO_FATAL_FAILURE(SetManagedNetworkPolicy(onc_source, test_policy));
pneubeck908e55b2015-09-30 16:53:49314 }
315
pmarko93bc5d72017-04-27 10:58:28316 void SetupCertificateConfigMatchingIssuerCN(
Pavol Marko0b3fedd2018-10-29 11:57:20317 ::onc::ONCSource onc_source,
pmarko93bc5d72017-04-27 10:58:28318 client_cert::ClientCertConfig* client_cert_config) {
Pavol Marko0b3fedd2018-10-29 11:57:20319 const char* test_onc_pattern = R"(
320 {
321 "Issuer": {
322 "CommonName": "B CA"
323 }
324 })";
pmarko93bc5d72017-04-27 10:58:28325 std::string error;
326 std::unique_ptr<base::Value> onc_pattern_value =
Lei Zhang668c8ab2019-02-16 02:49:36327 base::JSONReader::ReadAndReturnErrorDeprecated(
328 test_onc_pattern, base::JSON_ALLOW_TRAILING_COMMAS, nullptr,
329 &error);
pmarko93bc5d72017-04-27 10:58:28330 ASSERT_TRUE(onc_pattern_value) << error;
331
332 base::DictionaryValue* onc_pattern_dict;
333 onc_pattern_value->GetAsDictionary(&onc_pattern_dict);
334
335 client_cert_config->onc_source = onc_source;
Pavol Marko0b3fedd2018-10-29 11:57:20336 client_cert_config->client_cert_type = ::onc::client_cert::kPattern;
pmarko93bc5d72017-04-27 10:58:28337 client_cert_config->pattern.ReadFromONCDictionary(*onc_pattern_dict);
338 }
339
pneubeck908e55b2015-09-30 16:53:49340 // Sets up a policy with a certificate pattern that matches any client cert
341 // that is signed by the test CA cert (stored in |test_ca_cert_pem_|). In
[email protected]72b3a7e2013-08-13 15:30:04342 // particular it will match the test client cert.
Pavol Marko0b3fedd2018-10-29 11:57:20343 void SetupPolicyMatchingIssuerPEM(::onc::ONCSource onc_source,
pmarko93bc5d72017-04-27 10:58:28344 const std::string& identity) {
Pavol Marko0b3fedd2018-10-29 11:57:20345 const char* test_policy_template = R"(
346 [ { "GUID": "wifi_stub",
347 "Name": "wifi_stub",
348 "Type": "WiFi",
349 "WiFi": {
350 "Security": "WPA-EAP",
351 "SSID": "wifi_ssid",
352 "EAP": {
353 "Identity": "%s",
354 "Outer": "EAP-TLS",
355 "ClientCertType": "Pattern",
356 "ClientCertPattern": {
357 "IssuerCAPEMs": [ "%s" ]
358 }
359 }
360 }
361 } ])";
cernekee969c5122016-03-03 19:28:31362 std::string policy_json = base::StringPrintf(
Pavol Marko6ce72d02017-12-15 00:34:24363 test_policy_template, identity.c_str(), test_ca_cert_pem_.c_str());
Pavol Marko0b3fedd2018-10-29 11:57:20364 ASSERT_NO_FATAL_FAILURE(SetManagedNetworkPolicy(onc_source, policy_json));
365 }
[email protected]72b3a7e2013-08-13 15:30:04366
Pavol Marko0b3fedd2018-10-29 11:57:20367 void SetManagedNetworkPolicy(::onc::ONCSource onc_source,
368 base::StringPiece policy_json) {
[email protected]72b3a7e2013-08-13 15:30:04369 std::string error;
dcheng0a6e80c2016-04-08 18:37:38370 std::unique_ptr<base::Value> policy_value =
Lei Zhang668c8ab2019-02-16 02:49:36371 base::JSONReader::ReadAndReturnErrorDeprecated(
dcheng0a6e80c2016-04-08 18:37:38372 policy_json, base::JSON_ALLOW_TRAILING_COMMAS, nullptr, &error);
[email protected]72b3a7e2013-08-13 15:30:04373 ASSERT_TRUE(policy_value) << error;
374
emaxx98181cd2015-11-17 18:08:12375 base::ListValue* policy = nullptr;
[email protected]72b3a7e2013-08-13 15:30:04376 ASSERT_TRUE(policy_value->GetAsList(&policy));
377
pmarko93bc5d72017-04-27 10:58:28378 std::string user_hash =
Pavol Marko0b3fedd2018-10-29 11:57:20379 onc_source == ::onc::ONC_SOURCE_USER_POLICY ? kUserHash : "";
[email protected]72b3a7e2013-08-13 15:30:04380 managed_config_handler_->SetPolicy(
pmarko93bc5d72017-04-27 10:58:28381 onc_source, user_hash, *policy,
[email protected]e5ed56eb2013-10-21 21:07:53382 base::DictionaryValue() /* no global network config */);
[email protected]72b3a7e2013-08-13 15:30:04383 }
384
emaxx98181cd2015-11-17 18:08:12385 void SetWifiState(const std::string& state) {
386 ASSERT_TRUE(service_test_->SetServiceProperty(
jdoerrie122c4da2017-03-06 11:12:04387 kWifiStub, shill::kStateProperty, base::Value(state)));
emaxx98181cd2015-11-17 18:08:12388 }
389
cernekee969c5122016-03-03 19:28:31390 void GetServiceProperty(const std::string& prop_name,
391 std::string* prop_value) {
392 prop_value->clear();
[email protected]72b3a7e2013-08-13 15:30:04393 const base::DictionaryValue* properties =
394 service_test_->GetServiceProperties(kWifiStub);
395 if (!properties)
396 return;
cernekee969c5122016-03-03 19:28:31397 properties->GetStringWithoutPathExpansion(prop_name, prop_value);
[email protected]72b3a7e2013-08-13 15:30:04398 }
399
Pavol Marko0b3fedd2018-10-29 11:57:20400 // Returns a list of all certificates that are stored on |test_nsscertdb_|'s
401 // private slot.
402 net::ScopedCERTCertificateList ListCertsOnPrivateSlot() {
403 net::ScopedCERTCertificateList certs;
404 base::RunLoop run_loop;
405 test_nsscertdb_->ListCertsInSlot(
David Benjamin375809b2018-11-07 18:28:56406 base::BindOnce(&OnListCertsDone, run_loop.QuitClosure(), &certs),
Pavol Marko0b3fedd2018-10-29 11:57:20407 test_nsscertdb_->GetPrivateSlot().get());
408 run_loop.Run();
409 return certs;
410 }
411
Gabriel Charette694c3c332019-08-19 14:53:05412 base::test::TaskEnvironment task_environment_;
pmarko93bc5d72017-04-27 10:58:28413 int network_properties_changed_count_ = 0;
[email protected]5fffe152014-07-30 19:40:09414 std::string test_cert_id_;
dcheng0a6e80c2016-04-08 18:37:38415 std::unique_ptr<base::SimpleTestClock> test_clock_;
416 std::unique_ptr<ClientCertResolver> client_cert_resolver_;
Pavol Marko5006c4c2018-10-09 12:58:10417 NetworkCertLoader* network_cert_loader_ = nullptr;
Pavol Marko0b3fedd2018-10-29 11:57:20418 std::unique_ptr<net::NSSCertDatabaseChromeOS> test_nsscertdb_;
Pavol Markoa835cfa2019-02-18 12:38:34419 std::unique_ptr<net::NSSCertDatabaseChromeOS> test_system_nsscertdb_;
[email protected]72b3a7e2013-08-13 15:30:04420
421 private:
pneubeckf501c652014-11-05 21:03:57422 // ClientCertResolver::Observer:
423 void ResolveRequestCompleted(bool network_properties_changed) override {
424 if (network_properties_changed)
425 ++network_properties_changed_count_;
426 }
427
pmarko93bc5d72017-04-27 10:58:28428 ShillServiceClient::TestInterface* service_test_ = nullptr;
429 ShillProfileClient::TestInterface* profile_test_ = nullptr;
dcheng0a6e80c2016-04-08 18:37:38430 std::unique_ptr<NetworkStateHandler> network_state_handler_;
431 std::unique_ptr<NetworkProfileHandler> network_profile_handler_;
432 std::unique_ptr<NetworkConfigurationHandler> network_config_handler_;
433 std::unique_ptr<ManagedNetworkConfigurationHandlerImpl>
434 managed_config_handler_;
Matt Mueller0d0c1422017-09-07 18:08:38435 net::ScopedCERTCertificate test_client_cert_;
pneubeckf501c652014-11-05 21:03:57436 std::string test_ca_cert_pem_;
437 crypto::ScopedTestNSSDB test_nssdb_;
pmarko93bc5d72017-04-27 10:58:28438 crypto::ScopedTestNSSDB test_system_nssdb_;
[email protected]72b3a7e2013-08-13 15:30:04439
440 DISALLOW_COPY_AND_ASSIGN(ClientCertResolverTest);
441};
442
443TEST_F(ClientCertResolverTest, NoMatchingCertificates) {
cernekee969c5122016-03-03 19:28:31444 SetupTestCerts("client_1", false /* do not import the issuer */);
Pavol Marko5006c4c2018-10-09 12:58:10445 StartNetworkCertLoader();
pneubeckd0f72112014-10-24 13:30:00446 SetupWifi();
Gabriel Charette694c3c332019-08-19 14:53:05447 task_environment_.RunUntilIdle();
pneubeckf501c652014-11-05 21:03:57448 network_properties_changed_count_ = 0;
pneubeckd0f72112014-10-24 13:30:00449 SetupNetworkHandlers();
Pavol Marko0b3fedd2018-10-29 11:57:20450 ASSERT_NO_FATAL_FAILURE(
451 SetupPolicyMatchingIssuerPEM(::onc::ONC_SOURCE_USER_POLICY, ""));
Gabriel Charette694c3c332019-08-19 14:53:05452 task_environment_.RunUntilIdle();
[email protected]72b3a7e2013-08-13 15:30:04453
454 // Verify that no client certificate was configured.
455 std::string pkcs11_id;
cernekee969c5122016-03-03 19:28:31456 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
[email protected]1e042d72014-07-03 12:09:17457 EXPECT_EQ(std::string(), pkcs11_id);
pneubeckf501c652014-11-05 21:03:57458 EXPECT_EQ(1, network_properties_changed_count_);
459 EXPECT_FALSE(client_cert_resolver_->IsAnyResolveTaskRunning());
[email protected]72b3a7e2013-08-13 15:30:04460}
461
pneubeck908e55b2015-09-30 16:53:49462TEST_F(ClientCertResolverTest, MatchIssuerCNWithoutIssuerInstalled) {
cernekee969c5122016-03-03 19:28:31463 SetupTestCerts("client_1", false /* do not import the issuer */);
pneubeckd0f72112014-10-24 13:30:00464 SetupWifi();
Gabriel Charette694c3c332019-08-19 14:53:05465 task_environment_.RunUntilIdle();
pneubeckd0f72112014-10-24 13:30:00466
467 SetupNetworkHandlers();
Pavol Marko0b3fedd2018-10-29 11:57:20468 ASSERT_NO_FATAL_FAILURE(
469 SetupPolicyMatchingIssuerCN(::onc::ONC_SOURCE_USER_POLICY));
Gabriel Charette694c3c332019-08-19 14:53:05470 task_environment_.RunUntilIdle();
pneubeck908e55b2015-09-30 16:53:49471
472 network_properties_changed_count_ = 0;
Pavol Marko5006c4c2018-10-09 12:58:10473 StartNetworkCertLoader();
Gabriel Charette694c3c332019-08-19 14:53:05474 task_environment_.RunUntilIdle();
pneubeck908e55b2015-09-30 16:53:49475
476 // Verify that the resolver positively matched the pattern in the policy with
477 // the test client cert and configured the network.
478 std::string pkcs11_id;
cernekee969c5122016-03-03 19:28:31479 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
pneubeck908e55b2015-09-30 16:53:49480 EXPECT_EQ(test_cert_id_, pkcs11_id);
481 EXPECT_EQ(1, network_properties_changed_count_);
482}
483
Pavol Marko6ce72d02017-12-15 00:34:24484// Test that matching works on a certificate with invalid characters in a
485// PrintableString field. See crbug.com/788655.
486TEST_F(ClientCertResolverTest, MatchSubjectOrgOnBadPrintableStringCert) {
487 ASSERT_NO_FATAL_FAILURE(SetupTestCertWithBadPrintableString());
488
489 SetupWifi();
Gabriel Charette694c3c332019-08-19 14:53:05490 task_environment_.RunUntilIdle();
Pavol Marko6ce72d02017-12-15 00:34:24491
492 SetupNetworkHandlers();
493 ASSERT_NO_FATAL_FAILURE(
494 SetupPolicyMatchingSubjectOrgForBadPrintableStringCert(
Pavol Marko0b3fedd2018-10-29 11:57:20495 ::onc::ONC_SOURCE_USER_POLICY));
Gabriel Charette694c3c332019-08-19 14:53:05496 task_environment_.RunUntilIdle();
Pavol Marko6ce72d02017-12-15 00:34:24497
498 network_properties_changed_count_ = 0;
Pavol Marko5006c4c2018-10-09 12:58:10499 StartNetworkCertLoader();
Gabriel Charette694c3c332019-08-19 14:53:05500 task_environment_.RunUntilIdle();
Pavol Marko6ce72d02017-12-15 00:34:24501
502 // Verify that the resolver positively matched the pattern in the policy with
503 // the test client cert and configured the network.
504 std::string pkcs11_id;
505 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
506 EXPECT_EQ(test_cert_id_, pkcs11_id);
507 EXPECT_EQ(1, network_properties_changed_count_);
508}
509
pneubeck908e55b2015-09-30 16:53:49510TEST_F(ClientCertResolverTest, ResolveOnCertificatesLoaded) {
cernekee969c5122016-03-03 19:28:31511 SetupTestCerts("client_1", true /* import issuer */);
pneubeck908e55b2015-09-30 16:53:49512 SetupWifi();
Gabriel Charette694c3c332019-08-19 14:53:05513 task_environment_.RunUntilIdle();
pneubeck908e55b2015-09-30 16:53:49514
515 SetupNetworkHandlers();
Pavol Marko0b3fedd2018-10-29 11:57:20516 ASSERT_NO_FATAL_FAILURE(
517 SetupPolicyMatchingIssuerPEM(::onc::ONC_SOURCE_USER_POLICY, ""));
Gabriel Charette694c3c332019-08-19 14:53:05518 task_environment_.RunUntilIdle();
[email protected]72b3a7e2013-08-13 15:30:04519
pneubeckf501c652014-11-05 21:03:57520 network_properties_changed_count_ = 0;
Pavol Marko5006c4c2018-10-09 12:58:10521 StartNetworkCertLoader();
Gabriel Charette694c3c332019-08-19 14:53:05522 task_environment_.RunUntilIdle();
[email protected]72b3a7e2013-08-13 15:30:04523
524 // Verify that the resolver positively matched the pattern in the policy with
525 // the test client cert and configured the network.
526 std::string pkcs11_id;
cernekee969c5122016-03-03 19:28:31527 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
[email protected]5fffe152014-07-30 19:40:09528 EXPECT_EQ(test_cert_id_, pkcs11_id);
pneubeckf501c652014-11-05 21:03:57529 EXPECT_EQ(1, network_properties_changed_count_);
[email protected]72b3a7e2013-08-13 15:30:04530}
531
532TEST_F(ClientCertResolverTest, ResolveAfterPolicyApplication) {
cernekee969c5122016-03-03 19:28:31533 SetupTestCerts("client_1", true /* import issuer */);
pneubeckd0f72112014-10-24 13:30:00534 SetupWifi();
Gabriel Charette694c3c332019-08-19 14:53:05535 task_environment_.RunUntilIdle();
Pavol Marko5006c4c2018-10-09 12:58:10536 StartNetworkCertLoader();
[email protected]72b3a7e2013-08-13 15:30:04537 SetupNetworkHandlers();
Gabriel Charette694c3c332019-08-19 14:53:05538 task_environment_.RunUntilIdle();
[email protected]72b3a7e2013-08-13 15:30:04539
[email protected]1e042d72014-07-03 12:09:17540 // Policy application will trigger the ClientCertResolver.
pneubeckf501c652014-11-05 21:03:57541 network_properties_changed_count_ = 0;
Pavol Marko0b3fedd2018-10-29 11:57:20542 ASSERT_NO_FATAL_FAILURE(
543 SetupPolicyMatchingIssuerPEM(::onc::ONC_SOURCE_USER_POLICY, ""));
Gabriel Charette694c3c332019-08-19 14:53:05544 task_environment_.RunUntilIdle();
[email protected]72b3a7e2013-08-13 15:30:04545
546 // Verify that the resolver positively matched the pattern in the policy with
547 // the test client cert and configured the network.
548 std::string pkcs11_id;
cernekee969c5122016-03-03 19:28:31549 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
[email protected]5fffe152014-07-30 19:40:09550 EXPECT_EQ(test_cert_id_, pkcs11_id);
pneubeckf501c652014-11-05 21:03:57551 EXPECT_EQ(1, network_properties_changed_count_);
[email protected]72b3a7e2013-08-13 15:30:04552}
553
emaxx98181cd2015-11-17 18:08:12554TEST_F(ClientCertResolverTest, ExpiringCertificate) {
cernekee969c5122016-03-03 19:28:31555 SetupTestCerts("client_1", true /* import issuer */);
emaxx98181cd2015-11-17 18:08:12556 SetupWifi();
Gabriel Charette694c3c332019-08-19 14:53:05557 task_environment_.RunUntilIdle();
emaxx98181cd2015-11-17 18:08:12558
559 SetupNetworkHandlers();
Pavol Marko0b3fedd2018-10-29 11:57:20560 ASSERT_NO_FATAL_FAILURE(
561 SetupPolicyMatchingIssuerPEM(::onc::ONC_SOURCE_USER_POLICY, ""));
Gabriel Charette694c3c332019-08-19 14:53:05562 task_environment_.RunUntilIdle();
emaxx98181cd2015-11-17 18:08:12563
Pavol Marko5006c4c2018-10-09 12:58:10564 StartNetworkCertLoader();
Gabriel Charette694c3c332019-08-19 14:53:05565 task_environment_.RunUntilIdle();
emaxx98181cd2015-11-17 18:08:12566
567 SetWifiState(shill::kStateOnline);
Gabriel Charette694c3c332019-08-19 14:53:05568 task_environment_.RunUntilIdle();
emaxx98181cd2015-11-17 18:08:12569
570 // Verify that the resolver positively matched the pattern in the policy with
571 // the test client cert and configured the network.
572 std::string pkcs11_id;
cernekee969c5122016-03-03 19:28:31573 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
emaxx98181cd2015-11-17 18:08:12574 EXPECT_EQ(test_cert_id_, pkcs11_id);
575
576 // Verify that, after the certificate expired and the network disconnection
Pavol Markod69d4302018-02-01 10:08:41577 // happens, no client certificate was configured and the ClientCertResolver
578 // notified its observers with |network_properties_changed| = true.
579 network_properties_changed_count_ = 0;
emaxx98181cd2015-11-17 18:08:12580 test_clock_->SetNow(base::Time::Max());
581 SetWifiState(shill::kStateOffline);
Gabriel Charette694c3c332019-08-19 14:53:05582 task_environment_.RunUntilIdle();
cernekee969c5122016-03-03 19:28:31583 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
emaxx98181cd2015-11-17 18:08:12584 EXPECT_EQ(std::string(), pkcs11_id);
Pavol Markod69d4302018-02-01 10:08:41585 EXPECT_EQ(1, network_properties_changed_count_);
586}
587
588// Test for crbug.com/765489. When the ClientCertResolver re-resolves a network
589// as response to a NetworkConnectionStateChanged notification, and the
590// resulting cert is the same as the last resolved cert, it should not call
591// ResolveRequestCompleted with |network_properties_changed| = true.
592TEST_F(ClientCertResolverTest, SameCertAfterNetworkConnectionStateChanged) {
593 SetupTestCerts("client_1", true /* import issuer */);
594 SetupWifi();
Gabriel Charette694c3c332019-08-19 14:53:05595 task_environment_.RunUntilIdle();
Pavol Markod69d4302018-02-01 10:08:41596
597 SetupNetworkHandlers();
Pavol Marko0b3fedd2018-10-29 11:57:20598 ASSERT_NO_FATAL_FAILURE(
599 SetupPolicyMatchingIssuerPEM(::onc::ONC_SOURCE_USER_POLICY, ""));
Gabriel Charette694c3c332019-08-19 14:53:05600 task_environment_.RunUntilIdle();
Pavol Markod69d4302018-02-01 10:08:41601
Pavol Marko5006c4c2018-10-09 12:58:10602 StartNetworkCertLoader();
Gabriel Charette694c3c332019-08-19 14:53:05603 task_environment_.RunUntilIdle();
Pavol Markod69d4302018-02-01 10:08:41604
605 SetWifiState(shill::kStateOnline);
Gabriel Charette694c3c332019-08-19 14:53:05606 task_environment_.RunUntilIdle();
Pavol Markod69d4302018-02-01 10:08:41607
608 // Verify that the resolver positively matched the pattern in the policy with
609 // the test client cert and configured the network.
610 std::string pkcs11_id;
611 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
612 EXPECT_EQ(test_cert_id_, pkcs11_id);
613
614 // Verify that after the network disconnection happens, the configured
615 // certificate doesn't change and ClientCertResolver does not notify its
616 // observers with |network_properties_changed| = true.
617 network_properties_changed_count_ = 0;
618 SetWifiState(shill::kStateOffline);
Gabriel Charette694c3c332019-08-19 14:53:05619 task_environment_.RunUntilIdle();
Pavol Markod69d4302018-02-01 10:08:41620 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
621 EXPECT_EQ(test_cert_id_, pkcs11_id);
622 EXPECT_EQ(0, network_properties_changed_count_);
emaxx98181cd2015-11-17 18:08:12623}
624
pmarko93bc5d72017-04-27 10:58:28625TEST_F(ClientCertResolverTest, UserPolicyUsesSystemToken) {
626 SetupTestCertInSystemToken("client_1");
627 SetupWifi();
Gabriel Charette694c3c332019-08-19 14:53:05628 task_environment_.RunUntilIdle();
pmarko93bc5d72017-04-27 10:58:28629
630 SetupNetworkHandlers();
Pavol Marko0b3fedd2018-10-29 11:57:20631 ASSERT_NO_FATAL_FAILURE(
632 SetupPolicyMatchingIssuerCN(::onc::ONC_SOURCE_USER_POLICY));
Gabriel Charette694c3c332019-08-19 14:53:05633 task_environment_.RunUntilIdle();
pmarko93bc5d72017-04-27 10:58:28634
Pavol Marko5006c4c2018-10-09 12:58:10635 StartNetworkCertLoader();
Gabriel Charette694c3c332019-08-19 14:53:05636 task_environment_.RunUntilIdle();
Pavol Markoa835cfa2019-02-18 12:38:34637 ASSERT_EQ(1U, network_cert_loader_->client_certs().size());
638 EXPECT_TRUE(network_cert_loader_->client_certs()[0].is_device_wide());
pmarko93bc5d72017-04-27 10:58:28639
640 // Verify that the resolver positively matched the pattern in the policy with
641 // the test client cert and configured the network.
642 std::string pkcs11_id;
643 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
644 EXPECT_EQ(test_cert_id_, pkcs11_id);
645}
646
647TEST_F(ClientCertResolverTest, UserPolicyUsesSystemTokenSync) {
648 SetupTestCertInSystemToken("client_1");
Pavol Marko5006c4c2018-10-09 12:58:10649 StartNetworkCertLoader();
Gabriel Charette694c3c332019-08-19 14:53:05650 task_environment_.RunUntilIdle();
pmarko93bc5d72017-04-27 10:58:28651
652 client_cert::ClientCertConfig client_cert_config;
Pavol Marko0b3fedd2018-10-29 11:57:20653 SetupCertificateConfigMatchingIssuerCN(::onc::ONC_SOURCE_USER_POLICY,
pmarko93bc5d72017-04-27 10:58:28654 &client_cert_config);
655
656 base::DictionaryValue shill_properties;
Pavol Marko0b3fedd2018-10-29 11:57:20657 ClientCertResolver::ResolveClientCertificateSync(
pmarko93bc5d72017-04-27 10:58:28658 client_cert::CONFIG_TYPE_EAP, client_cert_config, &shill_properties);
659 std::string pkcs11_id;
660 shill_properties.GetStringWithoutPathExpansion(shill::kEapCertIdProperty,
661 &pkcs11_id);
662 EXPECT_EQ(test_cert_id_, pkcs11_id);
663}
664
665TEST_F(ClientCertResolverTest, DevicePolicyUsesSystemToken) {
666 SetupTestCertInSystemToken("client_1");
667 SetupWifi();
Gabriel Charette694c3c332019-08-19 14:53:05668 task_environment_.RunUntilIdle();
pmarko93bc5d72017-04-27 10:58:28669
670 SetupNetworkHandlers();
Pavol Marko0b3fedd2018-10-29 11:57:20671 ASSERT_NO_FATAL_FAILURE(
672 SetupPolicyMatchingIssuerCN(::onc::ONC_SOURCE_USER_POLICY));
Gabriel Charette694c3c332019-08-19 14:53:05673 task_environment_.RunUntilIdle();
pmarko93bc5d72017-04-27 10:58:28674
Pavol Marko5006c4c2018-10-09 12:58:10675 StartNetworkCertLoader();
Gabriel Charette694c3c332019-08-19 14:53:05676 task_environment_.RunUntilIdle();
Pavol Markoa835cfa2019-02-18 12:38:34677 ASSERT_EQ(1U, network_cert_loader_->client_certs().size());
678 EXPECT_TRUE(network_cert_loader_->client_certs()[0].is_device_wide());
pmarko93bc5d72017-04-27 10:58:28679
680 // Verify that the resolver positively matched the pattern in the policy with
681 // the test client cert and configured the network.
682 std::string pkcs11_id;
683 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
684 EXPECT_EQ(test_cert_id_, pkcs11_id);
685}
686
687TEST_F(ClientCertResolverTest, DevicePolicyUsesSystemTokenSync) {
688 SetupTestCertInSystemToken("client_1");
Pavol Marko5006c4c2018-10-09 12:58:10689 StartNetworkCertLoader();
Gabriel Charette694c3c332019-08-19 14:53:05690 task_environment_.RunUntilIdle();
pmarko93bc5d72017-04-27 10:58:28691
692 client_cert::ClientCertConfig client_cert_config;
Pavol Marko0b3fedd2018-10-29 11:57:20693 SetupCertificateConfigMatchingIssuerCN(::onc::ONC_SOURCE_DEVICE_POLICY,
pmarko93bc5d72017-04-27 10:58:28694 &client_cert_config);
695
696 base::DictionaryValue shill_properties;
Pavol Marko0b3fedd2018-10-29 11:57:20697 ClientCertResolver::ResolveClientCertificateSync(
pmarko93bc5d72017-04-27 10:58:28698 client_cert::CONFIG_TYPE_EAP, client_cert_config, &shill_properties);
699 std::string pkcs11_id;
700 shill_properties.GetStringWithoutPathExpansion(shill::kEapCertIdProperty,
701 &pkcs11_id);
702 EXPECT_EQ(test_cert_id_, pkcs11_id);
703}
704
705TEST_F(ClientCertResolverTest, DevicePolicyDoesNotUseUserToken) {
706 SetupTestCerts("client_1", false /* do not import the issuer */);
707 SetupWifi();
Gabriel Charette694c3c332019-08-19 14:53:05708 task_environment_.RunUntilIdle();
pmarko93bc5d72017-04-27 10:58:28709
710 SetupNetworkHandlers();
Pavol Marko0b3fedd2018-10-29 11:57:20711 ASSERT_NO_FATAL_FAILURE(
712 SetupPolicyMatchingIssuerCN(::onc::ONC_SOURCE_DEVICE_POLICY));
Gabriel Charette694c3c332019-08-19 14:53:05713 task_environment_.RunUntilIdle();
pmarko93bc5d72017-04-27 10:58:28714
715 network_properties_changed_count_ = 0;
Pavol Marko5006c4c2018-10-09 12:58:10716 StartNetworkCertLoader();
Gabriel Charette694c3c332019-08-19 14:53:05717 task_environment_.RunUntilIdle();
Pavol Markoa835cfa2019-02-18 12:38:34718 ASSERT_EQ(1U, network_cert_loader_->client_certs().size());
719 EXPECT_FALSE(network_cert_loader_->client_certs()[0].is_device_wide());
pmarko93bc5d72017-04-27 10:58:28720
721 // Verify that no client certificate was configured.
722 std::string pkcs11_id;
723 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
724 EXPECT_EQ(std::string(), pkcs11_id);
725 EXPECT_EQ(1, network_properties_changed_count_);
726 EXPECT_FALSE(client_cert_resolver_->IsAnyResolveTaskRunning());
727}
728
729TEST_F(ClientCertResolverTest, DevicePolicyDoesNotUseUserTokenSync) {
730 SetupTestCerts("client_1", false /* do not import the issuer */);
Pavol Marko5006c4c2018-10-09 12:58:10731 StartNetworkCertLoader();
Gabriel Charette694c3c332019-08-19 14:53:05732 task_environment_.RunUntilIdle();
pmarko93bc5d72017-04-27 10:58:28733
734 client_cert::ClientCertConfig client_cert_config;
Pavol Marko0b3fedd2018-10-29 11:57:20735 SetupCertificateConfigMatchingIssuerCN(::onc::ONC_SOURCE_DEVICE_POLICY,
pmarko93bc5d72017-04-27 10:58:28736 &client_cert_config);
737
738 base::DictionaryValue shill_properties;
Pavol Marko0b3fedd2018-10-29 11:57:20739 ClientCertResolver::ResolveClientCertificateSync(
pmarko93bc5d72017-04-27 10:58:28740 client_cert::CONFIG_TYPE_EAP, client_cert_config, &shill_properties);
741 std::string pkcs11_id;
742 shill_properties.GetStringWithoutPathExpansion(shill::kEapCertIdProperty,
743 &pkcs11_id);
744 EXPECT_EQ(std::string(), pkcs11_id);
745}
746
cernekee969c5122016-03-03 19:28:31747TEST_F(ClientCertResolverTest, PopulateIdentityFromCert) {
748 SetupTestCerts("client_3", true /* import issuer */);
749 SetupWifi();
Gabriel Charette694c3c332019-08-19 14:53:05750 task_environment_.RunUntilIdle();
cernekee969c5122016-03-03 19:28:31751
752 SetupNetworkHandlers();
Pavol Marko0b3fedd2018-10-29 11:57:20753 ASSERT_NO_FATAL_FAILURE(SetupPolicyMatchingIssuerPEM(
754 ::onc::ONC_SOURCE_USER_POLICY, "${CERT_SAN_EMAIL}"));
Gabriel Charette694c3c332019-08-19 14:53:05755 task_environment_.RunUntilIdle();
cernekee969c5122016-03-03 19:28:31756
757 network_properties_changed_count_ = 0;
Pavol Marko5006c4c2018-10-09 12:58:10758 StartNetworkCertLoader();
Gabriel Charette694c3c332019-08-19 14:53:05759 task_environment_.RunUntilIdle();
cernekee969c5122016-03-03 19:28:31760
761 // Verify that the resolver read the subjectAltName email field from the
762 // cert, and wrote it into the shill service entry.
763 std::string identity;
764 GetServiceProperty(shill::kEapIdentityProperty, &identity);
765 EXPECT_EQ("[email protected]", identity);
766 EXPECT_EQ(1, network_properties_changed_count_);
767
768 // Verify that after changing the ONC policy to request a variant of the
769 // Microsoft Universal Principal Name field instead, the correct value is
770 // substituted into the shill service entry.
Pavol Marko0b3fedd2018-10-29 11:57:20771 ASSERT_NO_FATAL_FAILURE(SetupPolicyMatchingIssuerPEM(
772 ::onc::ONC_SOURCE_USER_POLICY, "upn-${CERT_SAN_UPN}-suffix"));
Gabriel Charette694c3c332019-08-19 14:53:05773 task_environment_.RunUntilIdle();
cernekee969c5122016-03-03 19:28:31774
775 GetServiceProperty(shill::kEapIdentityProperty, &identity);
776 EXPECT_EQ("[email protected]", identity);
777 EXPECT_EQ(2, network_properties_changed_count_);
Pavol Marko75f1569b2018-04-24 14:01:21778
779 // Verify that after changing the ONC policy to request the subject CommonName
780 // field, the correct value is substituted into the shill service entry.
Pavol Marko0b3fedd2018-10-29 11:57:20781 ASSERT_NO_FATAL_FAILURE(SetupPolicyMatchingIssuerPEM(
782 ::onc::ONC_SOURCE_USER_POLICY,
783 "subject-cn-${CERT_SUBJECT_COMMON_NAME}-suffix"));
Gabriel Charette694c3c332019-08-19 14:53:05784 task_environment_.RunUntilIdle();
Pavol Marko75f1569b2018-04-24 14:01:21785
786 GetServiceProperty(shill::kEapIdentityProperty, &identity);
787 EXPECT_EQ("subject-cn-Client Cert F-suffix", identity);
788 EXPECT_EQ(3, network_properties_changed_count_);
cernekee969c5122016-03-03 19:28:31789}
790
Pavol Marko75afb402017-11-07 09:23:40791// Test for crbug.com/781276. A notification which results in no networks to be
792// resolved should not alter the state of IsAnyResolveTaskRunning().
793TEST_F(ClientCertResolverTest, TestResolveTaskQueued) {
794 // Set up ClientCertResolver and let it run initially
795 SetupTestCerts("client_1", true /* import issuer */);
Pavol Marko5006c4c2018-10-09 12:58:10796 StartNetworkCertLoader();
Pavol Marko75afb402017-11-07 09:23:40797 SetupWifi();
798 SetupNetworkHandlers();
Pavol Marko0b3fedd2018-10-29 11:57:20799 ASSERT_NO_FATAL_FAILURE(
800 SetupPolicyMatchingIssuerPEM(::onc::ONC_SOURCE_USER_POLICY, ""));
Gabriel Charette694c3c332019-08-19 14:53:05801 task_environment_.RunUntilIdle();
Pavol Marko75afb402017-11-07 09:23:40802
803 // Pretend that policy was applied, this shall queue a resolving task.
804 static_cast<NetworkPolicyObserver*>(client_cert_resolver_.get())
805 ->PolicyAppliedToNetwork(kWifiStub);
806 EXPECT_TRUE(client_cert_resolver_->IsAnyResolveTaskRunning());
807 // Pretend that the network list has changed. One resolving task should still
808 // be queued.
809 static_cast<NetworkStateHandlerObserver*>(client_cert_resolver_.get())
810 ->NetworkListChanged();
811 EXPECT_TRUE(client_cert_resolver_->IsAnyResolveTaskRunning());
812 // Pretend that certificates have changed. One resolving task should still be
813 // queued.
Pavol Marko5006c4c2018-10-09 12:58:10814 static_cast<NetworkCertLoader::Observer*>(client_cert_resolver_.get())
Pavol Markoa835cfa2019-02-18 12:38:34815 ->OnCertificatesLoaded();
Pavol Marko75afb402017-11-07 09:23:40816 EXPECT_TRUE(client_cert_resolver_->IsAnyResolveTaskRunning());
817
Gabriel Charette694c3c332019-08-19 14:53:05818 task_environment_.RunUntilIdle();
Pavol Marko75afb402017-11-07 09:23:40819 EXPECT_FALSE(client_cert_resolver_->IsAnyResolveTaskRunning());
820 // Verify that the resolver positively matched the pattern in the policy with
821 // the test client cert and configured the network.
822 std::string pkcs11_id;
823 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
824 EXPECT_EQ(test_cert_id_, pkcs11_id);
825}
826
Pavol Marko0b3fedd2018-10-29 11:57:20827// Tests that a ClientCertRef reference is resolved by |ClientCertResolver|.
828// Uses the |CertificateImporterImpl| to import the client certificate from ONC
829// policy, ensuring that setting the cert's key's nickname (in the import step)
830// and evaluating it (in the matching step) work well together.
831TEST_F(ClientCertResolverTest, ResolveClientCertRef) {
832 const char* test_policy_network =
833 R"([ { "GUID": "wifi_stub",
834 "Name": "wifi_stub",
835 "Type": "WiFi",
836 "WiFi": {
837 "Security": "WPA-EAP",
838 "SSID": "wifi_ssid",
839 "EAP": {
840 "Identity": "TestIdentity",
841 "Outer": "EAP-TLS",
842 "ClientCertType": "Ref",
843 "ClientCertRef": "{some-unique-guid}"
844 }
845 }
846 } ])";
847
848 SetupWifi();
Gabriel Charette694c3c332019-08-19 14:53:05849 task_environment_.RunUntilIdle();
Pavol Marko0b3fedd2018-10-29 11:57:20850 StartNetworkCertLoader();
Gabriel Charette694c3c332019-08-19 14:53:05851 task_environment_.RunUntilIdle();
Pavol Marko0b3fedd2018-10-29 11:57:20852 SetupNetworkHandlers();
Gabriel Charette694c3c332019-08-19 14:53:05853 task_environment_.RunUntilIdle();
Pavol Marko0b3fedd2018-10-29 11:57:20854
855 // Make sure that expiring client certs don't cause issues.
856 test_clock_->SetNow(base::Time::Min());
857
858 // Apply the network policy.
859 network_properties_changed_count_ = 0;
860 ASSERT_NO_FATAL_FAILURE(SetManagedNetworkPolicy(::onc::ONC_SOURCE_USER_POLICY,
861 test_policy_network));
Gabriel Charette694c3c332019-08-19 14:53:05862 task_environment_.RunUntilIdle();
Pavol Marko0b3fedd2018-10-29 11:57:20863
864 // The referenced client cert does not exist yet, so expect that it has not
865 // been resolved.
866 std::string pkcs11_id;
867 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
868 EXPECT_TRUE(pkcs11_id.empty());
869 EXPECT_EQ(1, network_properties_changed_count_);
870
871 // Now import a client certificate which has the GUID required using the
872 // |CertificateImporterImpl|.
873 auto onc_parsed_certificates = OncParsedCertificatesForPkcs12File(
874 net::GetTestCertsDirectory().AppendASCII("client-empty-password.p12"),
875 "{some-unique-guid}");
876 ASSERT_TRUE(onc_parsed_certificates);
877
878 onc::CertificateImporterImpl importer(
Gabriel Charette694c3c332019-08-19 14:53:05879 task_environment_.GetMainThreadTaskRunner(), test_nsscertdb_.get());
Pavol Marko0b3fedd2018-10-29 11:57:20880 base::RunLoop import_loop;
881 importer.ImportClientCertificates(
882 onc_parsed_certificates->client_certificates(),
883 base::BindOnce(&OnImportCompleted, import_loop.QuitClosure()));
884 import_loop.Run();
Gabriel Charette694c3c332019-08-19 14:53:05885 task_environment_.RunUntilIdle();
Pavol Marko0b3fedd2018-10-29 11:57:20886
887 // Find the imported cert and get its id.
888 net::ScopedCERTCertificateList private_slot_certs = ListCertsOnPrivateSlot();
889 ASSERT_EQ(1u, private_slot_certs.size());
890 int slot_id = 0;
891 const std::string imported_cert_pkcs11_id =
892 NetworkCertLoader::GetPkcs11IdAndSlotForCert(private_slot_certs[0].get(),
893 &slot_id);
894 std::string imported_cert_formatted_pkcs11_id =
895 base::StringPrintf("%i:%s", slot_id, imported_cert_pkcs11_id.c_str());
896
897 // Verify that the resolver positively matched the pattern in the policy with
898 // the test client cert and configured the network.
899 GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id);
900 EXPECT_EQ(imported_cert_formatted_pkcs11_id, pkcs11_id);
901 EXPECT_EQ(2, network_properties_changed_count_);
902}
903
[email protected]72b3a7e2013-08-13 15:30:04904} // namespace chromeos