[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 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" |
| 5 | |
| 6 | #include <cert.h> |
| 7 | #include <pk11pub.h> |
| 8 | |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 9 | #include <memory> |
| 10 | |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 11 | #include "base/base64.h" |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 12 | #include "base/bind.h" |
| 13 | #include "base/bind_helpers.h" |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 14 | #include "base/callback_helpers.h" |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 15 | #include "base/files/file_path.h" |
thestig | b44bd35 | 2014-09-10 01:47:06 | [diff] [blame] | 16 | #include "base/files/file_util.h" |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 17 | #include "base/json/json_reader.h" |
avi | 6e1a22d | 2015-12-21 03:43:20 | [diff] [blame] | 18 | #include "base/macros.h" |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 19 | #include "base/run_loop.h" |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 20 | #include "base/strings/stringprintf.h" |
Francois Doray | ef35439 | 2017-07-28 15:18:02 | [diff] [blame] | 21 | #include "base/test/scoped_task_environment.h" |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 22 | #include "base/test/simple_test_clock.h" |
[email protected] | e5ed56eb | 2013-10-21 21:07:53 | [diff] [blame] | 23 | #include "base/values.h" |
Steven Bennetts | b4bf6cd | 2019-04-05 17:02:57 | [diff] [blame] | 24 | #include "chromeos/dbus/shill/shill_clients.h" |
Steven Bennetts | d11e440f | 2019-04-04 01:09:00 | [diff] [blame] | 25 | #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] | 1b4d5fc | 2013-08-19 22:35:07 | [diff] [blame] | 28 | #include "chromeos/network/managed_network_configuration_handler_impl.h" |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 29 | #include "chromeos/network/network_cert_loader.h" |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 30 | #include "chromeos/network/network_configuration_handler.h" |
| 31 | #include "chromeos/network/network_profile_handler.h" |
| 32 | #include "chromeos/network/network_state_handler.h" |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 33 | #include "chromeos/network/onc/onc_certificate_importer_impl.h" |
| 34 | #include "chromeos/network/onc/onc_test_utils.h" |
[email protected] | c72ace84 | 2014-05-15 08:47:32 | [diff] [blame] | 35 | #include "components/onc/onc_constants.h" |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 36 | #include "crypto/scoped_nss_types.h" |
| 37 | #include "crypto/scoped_test_nss_db.h" |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 38 | #include "net/base/net_errors.h" |
[email protected] | 69295ba | 2014-01-28 06:17:00 | [diff] [blame] | 39 | #include "net/cert/nss_cert_database_chromeos.h" |
Pavol Marko | 6ce72d0 | 2017-12-15 00:34:24 | [diff] [blame] | 40 | #include "net/cert/pem_tokenizer.h" |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 41 | #include "net/cert/x509_certificate.h" |
Matt Mueller | 0d0c142 | 2017-09-07 18:08:38 | [diff] [blame] | 42 | #include "net/cert/x509_util_nss.h" |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 43 | #include "net/test/cert_test_util.h" |
rsleevi | a69c79a | 2016-06-22 03:28:43 | [diff] [blame] | 44 | #include "net/test/test_data_directory.h" |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 45 | #include "testing/gtest/include/gtest/gtest.h" |
| 46 | #include "third_party/cros_system_api/dbus/service_constants.h" |
| 47 | |
| 48 | namespace chromeos { |
| 49 | |
| 50 | namespace { |
| 51 | |
Pavol Marko | 6ce72d0 | 2017-12-15 00:34:24 | [diff] [blame] | 52 | constexpr char kWifiStub[] = "wifi_stub"; |
| 53 | constexpr char kWifiSSID[] = "wifi_ssid"; |
| 54 | constexpr char kUserProfilePath[] = "user_profile"; |
| 55 | constexpr char kUserHash[] = "user_hash"; |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 56 | |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 57 | void OnImportCompleted(base::OnceClosure loop_quit_closure, bool success) { |
| 58 | EXPECT_TRUE(success); |
| 59 | std::move(loop_quit_closure).Run(); |
| 60 | } |
| 61 | |
| 62 | void 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. |
| 72 | std::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] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 91 | } // namespace |
| 92 | |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 93 | class ClientCertResolverTest : public testing::Test, |
| 94 | public ClientCertResolver::Observer { |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 95 | public: |
Chris Watkins | 2c529d6 | 2017-11-29 02:14:41 | [diff] [blame] | 96 | ClientCertResolverTest() = default; |
| 97 | ~ClientCertResolverTest() override = default; |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 98 | |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 99 | void SetUp() override { |
| 100 | ASSERT_TRUE(test_nssdb_.is_open()); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 101 | ASSERT_TRUE(test_system_nssdb_.is_open()); |
Pavol Marko | a835cfa | 2019-02-18 12:38:34 | [diff] [blame] | 102 | // 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>( |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 105 | crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot())), |
Pavol Marko | a835cfa | 2019-02-18 12:38:34 | [diff] [blame] | 106 | 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] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 115 | |
Steven Bennetts | b4bf6cd | 2019-04-05 17:02:57 | [diff] [blame] | 116 | shill_clients::InitializeFakes(); |
| 117 | service_test_ = ShillServiceClient::Get()->GetTestInterface(); |
| 118 | profile_test_ = ShillProfileClient::Get()->GetTestInterface(); |
pneubeck | d0f7211 | 2014-10-24 13:30:00 | [diff] [blame] | 119 | profile_test_->AddProfile(kUserProfilePath, kUserHash); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 120 | task_environment_.RunUntilIdle(); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 121 | service_test_->ClearServices(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 122 | task_environment_.RunUntilIdle(); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 123 | |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 124 | NetworkCertLoader::Initialize(); |
| 125 | network_cert_loader_ = NetworkCertLoader::Get(); |
| 126 | NetworkCertLoader::ForceHardwareBackedForTesting(); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 127 | } |
| 128 | |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 129 | void TearDown() override { |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 130 | if (client_cert_resolver_) |
| 131 | client_cert_resolver_->RemoveObserver(this); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 132 | client_cert_resolver_.reset(); |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 133 | test_clock_.reset(); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 134 | if (network_state_handler_) |
| 135 | network_state_handler_->Shutdown(); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 136 | managed_config_handler_.reset(); |
| 137 | network_config_handler_.reset(); |
| 138 | network_profile_handler_.reset(); |
| 139 | network_state_handler_.reset(); |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 140 | NetworkCertLoader::Shutdown(); |
Steven Bennetts | b4bf6cd | 2019-04-05 17:02:57 | [diff] [blame] | 141 | shill_clients::Shutdown(); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 142 | } |
| 143 | |
| 144 | protected: |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 145 | void StartNetworkCertLoader() { |
| 146 | network_cert_loader_->SetUserNSSDB(test_nsscertdb_.get()); |
Pavol Marko | a835cfa | 2019-02-18 12:38:34 | [diff] [blame] | 147 | network_cert_loader_->SetSystemNSSDB(test_system_nsscertdb_.get()); |
dcheng | 5adf8d2 | 2014-09-11 00:53:37 | [diff] [blame] | 148 | if (test_client_cert_.get()) { |
[email protected] | 5fffe15 | 2014-07-30 19:40:09 | [diff] [blame] | 149 | int slot_id = 0; |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 150 | const std::string pkcs11_id = |
| 151 | NetworkCertLoader::GetPkcs11IdAndSlotForCert(test_client_cert_.get(), |
| 152 | &slot_id); |
[email protected] | 5fffe15 | 2014-07-30 19:40:09 | [diff] [blame] | 153 | test_cert_id_ = base::StringPrintf("%i:%s", slot_id, pkcs11_id.c_str()); |
[email protected] | 1e042d7 | 2014-07-03 12:09:17 | [diff] [blame] | 154 | } |
| 155 | } |
| 156 | |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 157 | // Imports a client certificate. After a subsequent StartNetworkCertLoader() |
Pavol Marko | 6ce72d0 | 2017-12-15 00:34:24 | [diff] [blame] | 158 | // 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. |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 161 | void SetupTestCerts(const std::string& prefix, bool import_issuer) { |
pneubeck | 908e55b | 2015-09-30 16:53:49 | [diff] [blame] | 162 | // Load a CA cert. |
Matt Mueller | 0d0c142 | 2017-09-07 18:08:38 | [diff] [blame] | 163 | net::ScopedCERTCertificateList ca_cert_list = |
| 164 | net::CreateCERTCertificateListFromFile( |
| 165 | net::GetTestCertsDirectory(), prefix + "_ca.pem", |
| 166 | net::X509Certificate::FORMAT_AUTO); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 167 | ASSERT_TRUE(!ca_cert_list.empty()); |
Matt Mueller | 0d0c142 | 2017-09-07 18:08:38 | [diff] [blame] | 168 | net::x509_util::GetPEMEncoded(ca_cert_list[0].get(), &test_ca_cert_pem_); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 169 | ASSERT_TRUE(!test_ca_cert_pem_.empty()); |
| 170 | |
pneubeck | 908e55b | 2015-09-30 16:53:49 | [diff] [blame] | 171 | 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] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 179 | // Import a client cert signed by that CA. |
Matt Mueller | 0d0c142 | 2017-09-07 18:08:38 | [diff] [blame] | 180 | net::ImportClientCertAndKeyFromFile(net::GetTestCertsDirectory(), |
| 181 | prefix + ".pem", prefix + ".pk8", |
| 182 | test_nssdb_.slot(), &test_client_cert_); |
pneubeck | d0f7211 | 2014-10-24 13:30:00 | [diff] [blame] | 183 | ASSERT_TRUE(test_client_cert_.get()); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 184 | } |
| 185 | |
Pavol Marko | 6ce72d0 | 2017-12-15 00:34:24 | [diff] [blame] | 186 | // Imports a client certificate with a subject CommonName encoded as |
| 187 | // PrintableString, but containing invalid characters. It is imported into the |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 188 | // user slot. After a subsequent StartNetworkCertLoader() invocation, the |
| 189 | // PKCS#11 ID of the imported certificate will be stored in |test_cert_id_|. |
Pavol Marko | 6ce72d0 | 2017-12-15 00:34:24 | [diff] [blame] | 190 | 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 | |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 215 | void SetupTestCertInSystemToken(const std::string& prefix) { |
Matt Mueller | 0d0c142 | 2017-09-07 18:08:38 | [diff] [blame] | 216 | net::ImportClientCertAndKeyFromFile( |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 217 | net::GetTestCertsDirectory(), prefix + ".pem", prefix + ".pk8", |
Matt Mueller | 0d0c142 | 2017-09-07 18:08:38 | [diff] [blame] | 218 | test_system_nssdb_.slot(), &test_client_cert_); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 219 | ASSERT_TRUE(test_client_cert_.get()); |
| 220 | } |
| 221 | |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 222 | void SetupNetworkHandlers() { |
thestig | 1a5f12f0 | 2016-11-04 18:46:11 | [diff] [blame] | 223 | network_state_handler_ = NetworkStateHandler::InitializeForTest(); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 224 | network_profile_handler_.reset(new NetworkProfileHandler()); |
| 225 | network_config_handler_.reset(new NetworkConfigurationHandler()); |
[email protected] | 1b4d5fc | 2013-08-19 22:35:07 | [diff] [blame] | 226 | managed_config_handler_.reset(new ManagedNetworkConfigurationHandlerImpl()); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 227 | client_cert_resolver_.reset(new ClientCertResolver()); |
| 228 | |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 229 | test_clock_.reset(new base::SimpleTestClock); |
| 230 | test_clock_->SetNow(base::Time::Now()); |
| 231 | client_cert_resolver_->SetClockForTesting(test_clock_.get()); |
| 232 | |
[email protected] | fa0336f | 2014-06-12 22:08:38 | [diff] [blame] | 233 | network_profile_handler_->Init(); |
stevenjb | d97aaeee | 2015-01-08 22:40:59 | [diff] [blame] | 234 | network_config_handler_->Init(network_state_handler_.get(), |
fqj | fee5067a | 2015-11-13 20:12:59 | [diff] [blame] | 235 | 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 */); |
pneubeck | d0f7211 | 2014-10-24 13:30:00 | [diff] [blame] | 240 | // Run all notifications before starting the cert loader to reduce run time. |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 241 | task_environment_.RunUntilIdle(); |
pneubeck | d0f7211 | 2014-10-24 13:30:00 | [diff] [blame] | 242 | |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 243 | client_cert_resolver_->Init(network_state_handler_.get(), |
| 244 | managed_config_handler_.get()); |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 245 | client_cert_resolver_->AddObserver(this); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 246 | } |
| 247 | |
| 248 | void SetupWifi() { |
[email protected] | 1e042d7 | 2014-07-03 12:09:17 | [diff] [blame] | 249 | 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. |
jdoerrie | 122c4da | 2017-03-06 11:12:04 | [diff] [blame] | 257 | service_test_->SetServiceProperty(kWifiStub, shill::kEapCertIdProperty, |
| 258 | base::Value("invalid id")); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 259 | profile_test_->AddService(kUserProfilePath, kWifiStub); |
[email protected] | 1e042d7 | 2014-07-03 12:09:17 | [diff] [blame] | 260 | |
Steven Bennetts | b4bf6cd | 2019-04-05 17:02:57 | [diff] [blame] | 261 | ShillManagerClient::Get()->GetTestInterface()->AddManagerService(kWifiStub, |
| 262 | true); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 263 | } |
| 264 | |
pneubeck | 908e55b | 2015-09-30 16:53:49 | [diff] [blame] | 265 | // Sets up a policy with a certificate pattern that matches any client cert |
Pavol Marko | 6ce72d0 | 2017-12-15 00:34:24 | [diff] [blame] | 266 | // with a certain Issuer CN. It will match the test client cert imported by |
| 267 | // SetupTestCerts. |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 268 | 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 Marko | 6ce72d0 | 2017-12-15 00:34:24 | [diff] [blame] | 288 | } |
| 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 Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 294 | ::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)); |
pneubeck | 908e55b | 2015-09-30 16:53:49 | [diff] [blame] | 314 | } |
| 315 | |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 316 | void SetupCertificateConfigMatchingIssuerCN( |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 317 | ::onc::ONCSource onc_source, |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 318 | client_cert::ClientCertConfig* client_cert_config) { |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 319 | const char* test_onc_pattern = R"( |
| 320 | { |
| 321 | "Issuer": { |
| 322 | "CommonName": "B CA" |
| 323 | } |
| 324 | })"; |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 325 | std::string error; |
| 326 | std::unique_ptr<base::Value> onc_pattern_value = |
Lei Zhang | 668c8ab | 2019-02-16 02:49:36 | [diff] [blame] | 327 | base::JSONReader::ReadAndReturnErrorDeprecated( |
| 328 | test_onc_pattern, base::JSON_ALLOW_TRAILING_COMMAS, nullptr, |
| 329 | &error); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 330 | 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 Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 336 | client_cert_config->client_cert_type = ::onc::client_cert::kPattern; |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 337 | client_cert_config->pattern.ReadFromONCDictionary(*onc_pattern_dict); |
| 338 | } |
| 339 | |
pneubeck | 908e55b | 2015-09-30 16:53:49 | [diff] [blame] | 340 | // 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] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 342 | // particular it will match the test client cert. |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 343 | void SetupPolicyMatchingIssuerPEM(::onc::ONCSource onc_source, |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 344 | const std::string& identity) { |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 345 | 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 | } ])"; |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 362 | std::string policy_json = base::StringPrintf( |
Pavol Marko | 6ce72d0 | 2017-12-15 00:34:24 | [diff] [blame] | 363 | test_policy_template, identity.c_str(), test_ca_cert_pem_.c_str()); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 364 | ASSERT_NO_FATAL_FAILURE(SetManagedNetworkPolicy(onc_source, policy_json)); |
| 365 | } |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 366 | |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 367 | void SetManagedNetworkPolicy(::onc::ONCSource onc_source, |
| 368 | base::StringPiece policy_json) { |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 369 | std::string error; |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 370 | std::unique_ptr<base::Value> policy_value = |
Lei Zhang | 668c8ab | 2019-02-16 02:49:36 | [diff] [blame] | 371 | base::JSONReader::ReadAndReturnErrorDeprecated( |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 372 | policy_json, base::JSON_ALLOW_TRAILING_COMMAS, nullptr, &error); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 373 | ASSERT_TRUE(policy_value) << error; |
| 374 | |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 375 | base::ListValue* policy = nullptr; |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 376 | ASSERT_TRUE(policy_value->GetAsList(&policy)); |
| 377 | |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 378 | std::string user_hash = |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 379 | onc_source == ::onc::ONC_SOURCE_USER_POLICY ? kUserHash : ""; |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 380 | managed_config_handler_->SetPolicy( |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 381 | onc_source, user_hash, *policy, |
[email protected] | e5ed56eb | 2013-10-21 21:07:53 | [diff] [blame] | 382 | base::DictionaryValue() /* no global network config */); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 383 | } |
| 384 | |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 385 | void SetWifiState(const std::string& state) { |
| 386 | ASSERT_TRUE(service_test_->SetServiceProperty( |
jdoerrie | 122c4da | 2017-03-06 11:12:04 | [diff] [blame] | 387 | kWifiStub, shill::kStateProperty, base::Value(state))); |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 388 | } |
| 389 | |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 390 | void GetServiceProperty(const std::string& prop_name, |
| 391 | std::string* prop_value) { |
| 392 | prop_value->clear(); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 393 | const base::DictionaryValue* properties = |
| 394 | service_test_->GetServiceProperties(kWifiStub); |
| 395 | if (!properties) |
| 396 | return; |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 397 | properties->GetStringWithoutPathExpansion(prop_name, prop_value); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 398 | } |
| 399 | |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 400 | // 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 Benjamin | 375809b | 2018-11-07 18:28:56 | [diff] [blame] | 406 | base::BindOnce(&OnListCertsDone, run_loop.QuitClosure(), &certs), |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 407 | test_nsscertdb_->GetPrivateSlot().get()); |
| 408 | run_loop.Run(); |
| 409 | return certs; |
| 410 | } |
| 411 | |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 412 | base::test::TaskEnvironment task_environment_; |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 413 | int network_properties_changed_count_ = 0; |
[email protected] | 5fffe15 | 2014-07-30 19:40:09 | [diff] [blame] | 414 | std::string test_cert_id_; |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 415 | std::unique_ptr<base::SimpleTestClock> test_clock_; |
| 416 | std::unique_ptr<ClientCertResolver> client_cert_resolver_; |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 417 | NetworkCertLoader* network_cert_loader_ = nullptr; |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 418 | std::unique_ptr<net::NSSCertDatabaseChromeOS> test_nsscertdb_; |
Pavol Marko | a835cfa | 2019-02-18 12:38:34 | [diff] [blame] | 419 | std::unique_ptr<net::NSSCertDatabaseChromeOS> test_system_nsscertdb_; |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 420 | |
| 421 | private: |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 422 | // ClientCertResolver::Observer: |
| 423 | void ResolveRequestCompleted(bool network_properties_changed) override { |
| 424 | if (network_properties_changed) |
| 425 | ++network_properties_changed_count_; |
| 426 | } |
| 427 | |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 428 | ShillServiceClient::TestInterface* service_test_ = nullptr; |
| 429 | ShillProfileClient::TestInterface* profile_test_ = nullptr; |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 430 | 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 Mueller | 0d0c142 | 2017-09-07 18:08:38 | [diff] [blame] | 435 | net::ScopedCERTCertificate test_client_cert_; |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 436 | std::string test_ca_cert_pem_; |
| 437 | crypto::ScopedTestNSSDB test_nssdb_; |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 438 | crypto::ScopedTestNSSDB test_system_nssdb_; |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 439 | |
| 440 | DISALLOW_COPY_AND_ASSIGN(ClientCertResolverTest); |
| 441 | }; |
| 442 | |
| 443 | TEST_F(ClientCertResolverTest, NoMatchingCertificates) { |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 444 | SetupTestCerts("client_1", false /* do not import the issuer */); |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 445 | StartNetworkCertLoader(); |
pneubeck | d0f7211 | 2014-10-24 13:30:00 | [diff] [blame] | 446 | SetupWifi(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 447 | task_environment_.RunUntilIdle(); |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 448 | network_properties_changed_count_ = 0; |
pneubeck | d0f7211 | 2014-10-24 13:30:00 | [diff] [blame] | 449 | SetupNetworkHandlers(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 450 | ASSERT_NO_FATAL_FAILURE( |
| 451 | SetupPolicyMatchingIssuerPEM(::onc::ONC_SOURCE_USER_POLICY, "")); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 452 | task_environment_.RunUntilIdle(); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 453 | |
| 454 | // Verify that no client certificate was configured. |
| 455 | std::string pkcs11_id; |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 456 | GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id); |
[email protected] | 1e042d7 | 2014-07-03 12:09:17 | [diff] [blame] | 457 | EXPECT_EQ(std::string(), pkcs11_id); |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 458 | EXPECT_EQ(1, network_properties_changed_count_); |
| 459 | EXPECT_FALSE(client_cert_resolver_->IsAnyResolveTaskRunning()); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 460 | } |
| 461 | |
pneubeck | 908e55b | 2015-09-30 16:53:49 | [diff] [blame] | 462 | TEST_F(ClientCertResolverTest, MatchIssuerCNWithoutIssuerInstalled) { |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 463 | SetupTestCerts("client_1", false /* do not import the issuer */); |
pneubeck | d0f7211 | 2014-10-24 13:30:00 | [diff] [blame] | 464 | SetupWifi(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 465 | task_environment_.RunUntilIdle(); |
pneubeck | d0f7211 | 2014-10-24 13:30:00 | [diff] [blame] | 466 | |
| 467 | SetupNetworkHandlers(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 468 | ASSERT_NO_FATAL_FAILURE( |
| 469 | SetupPolicyMatchingIssuerCN(::onc::ONC_SOURCE_USER_POLICY)); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 470 | task_environment_.RunUntilIdle(); |
pneubeck | 908e55b | 2015-09-30 16:53:49 | [diff] [blame] | 471 | |
| 472 | network_properties_changed_count_ = 0; |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 473 | StartNetworkCertLoader(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 474 | task_environment_.RunUntilIdle(); |
pneubeck | 908e55b | 2015-09-30 16:53:49 | [diff] [blame] | 475 | |
| 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; |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 479 | GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id); |
pneubeck | 908e55b | 2015-09-30 16:53:49 | [diff] [blame] | 480 | EXPECT_EQ(test_cert_id_, pkcs11_id); |
| 481 | EXPECT_EQ(1, network_properties_changed_count_); |
| 482 | } |
| 483 | |
Pavol Marko | 6ce72d0 | 2017-12-15 00:34:24 | [diff] [blame] | 484 | // Test that matching works on a certificate with invalid characters in a |
| 485 | // PrintableString field. See crbug.com/788655. |
| 486 | TEST_F(ClientCertResolverTest, MatchSubjectOrgOnBadPrintableStringCert) { |
| 487 | ASSERT_NO_FATAL_FAILURE(SetupTestCertWithBadPrintableString()); |
| 488 | |
| 489 | SetupWifi(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 490 | task_environment_.RunUntilIdle(); |
Pavol Marko | 6ce72d0 | 2017-12-15 00:34:24 | [diff] [blame] | 491 | |
| 492 | SetupNetworkHandlers(); |
| 493 | ASSERT_NO_FATAL_FAILURE( |
| 494 | SetupPolicyMatchingSubjectOrgForBadPrintableStringCert( |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 495 | ::onc::ONC_SOURCE_USER_POLICY)); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 496 | task_environment_.RunUntilIdle(); |
Pavol Marko | 6ce72d0 | 2017-12-15 00:34:24 | [diff] [blame] | 497 | |
| 498 | network_properties_changed_count_ = 0; |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 499 | StartNetworkCertLoader(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 500 | task_environment_.RunUntilIdle(); |
Pavol Marko | 6ce72d0 | 2017-12-15 00:34:24 | [diff] [blame] | 501 | |
| 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 | |
pneubeck | 908e55b | 2015-09-30 16:53:49 | [diff] [blame] | 510 | TEST_F(ClientCertResolverTest, ResolveOnCertificatesLoaded) { |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 511 | SetupTestCerts("client_1", true /* import issuer */); |
pneubeck | 908e55b | 2015-09-30 16:53:49 | [diff] [blame] | 512 | SetupWifi(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 513 | task_environment_.RunUntilIdle(); |
pneubeck | 908e55b | 2015-09-30 16:53:49 | [diff] [blame] | 514 | |
| 515 | SetupNetworkHandlers(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 516 | ASSERT_NO_FATAL_FAILURE( |
| 517 | SetupPolicyMatchingIssuerPEM(::onc::ONC_SOURCE_USER_POLICY, "")); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 518 | task_environment_.RunUntilIdle(); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 519 | |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 520 | network_properties_changed_count_ = 0; |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 521 | StartNetworkCertLoader(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 522 | task_environment_.RunUntilIdle(); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 523 | |
| 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; |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 527 | GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id); |
[email protected] | 5fffe15 | 2014-07-30 19:40:09 | [diff] [blame] | 528 | EXPECT_EQ(test_cert_id_, pkcs11_id); |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 529 | EXPECT_EQ(1, network_properties_changed_count_); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 530 | } |
| 531 | |
| 532 | TEST_F(ClientCertResolverTest, ResolveAfterPolicyApplication) { |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 533 | SetupTestCerts("client_1", true /* import issuer */); |
pneubeck | d0f7211 | 2014-10-24 13:30:00 | [diff] [blame] | 534 | SetupWifi(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 535 | task_environment_.RunUntilIdle(); |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 536 | StartNetworkCertLoader(); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 537 | SetupNetworkHandlers(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 538 | task_environment_.RunUntilIdle(); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 539 | |
[email protected] | 1e042d7 | 2014-07-03 12:09:17 | [diff] [blame] | 540 | // Policy application will trigger the ClientCertResolver. |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 541 | network_properties_changed_count_ = 0; |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 542 | ASSERT_NO_FATAL_FAILURE( |
| 543 | SetupPolicyMatchingIssuerPEM(::onc::ONC_SOURCE_USER_POLICY, "")); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 544 | task_environment_.RunUntilIdle(); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 545 | |
| 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; |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 549 | GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id); |
[email protected] | 5fffe15 | 2014-07-30 19:40:09 | [diff] [blame] | 550 | EXPECT_EQ(test_cert_id_, pkcs11_id); |
pneubeck | f501c65 | 2014-11-05 21:03:57 | [diff] [blame] | 551 | EXPECT_EQ(1, network_properties_changed_count_); |
[email protected] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 552 | } |
| 553 | |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 554 | TEST_F(ClientCertResolverTest, ExpiringCertificate) { |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 555 | SetupTestCerts("client_1", true /* import issuer */); |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 556 | SetupWifi(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 557 | task_environment_.RunUntilIdle(); |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 558 | |
| 559 | SetupNetworkHandlers(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 560 | ASSERT_NO_FATAL_FAILURE( |
| 561 | SetupPolicyMatchingIssuerPEM(::onc::ONC_SOURCE_USER_POLICY, "")); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 562 | task_environment_.RunUntilIdle(); |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 563 | |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 564 | StartNetworkCertLoader(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 565 | task_environment_.RunUntilIdle(); |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 566 | |
| 567 | SetWifiState(shill::kStateOnline); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 568 | task_environment_.RunUntilIdle(); |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 569 | |
| 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; |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 573 | GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id); |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 574 | EXPECT_EQ(test_cert_id_, pkcs11_id); |
| 575 | |
| 576 | // Verify that, after the certificate expired and the network disconnection |
Pavol Marko | d69d430 | 2018-02-01 10:08:41 | [diff] [blame] | 577 | // happens, no client certificate was configured and the ClientCertResolver |
| 578 | // notified its observers with |network_properties_changed| = true. |
| 579 | network_properties_changed_count_ = 0; |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 580 | test_clock_->SetNow(base::Time::Max()); |
| 581 | SetWifiState(shill::kStateOffline); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 582 | task_environment_.RunUntilIdle(); |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 583 | GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id); |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 584 | EXPECT_EQ(std::string(), pkcs11_id); |
Pavol Marko | d69d430 | 2018-02-01 10:08:41 | [diff] [blame] | 585 | 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. |
| 592 | TEST_F(ClientCertResolverTest, SameCertAfterNetworkConnectionStateChanged) { |
| 593 | SetupTestCerts("client_1", true /* import issuer */); |
| 594 | SetupWifi(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 595 | task_environment_.RunUntilIdle(); |
Pavol Marko | d69d430 | 2018-02-01 10:08:41 | [diff] [blame] | 596 | |
| 597 | SetupNetworkHandlers(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 598 | ASSERT_NO_FATAL_FAILURE( |
| 599 | SetupPolicyMatchingIssuerPEM(::onc::ONC_SOURCE_USER_POLICY, "")); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 600 | task_environment_.RunUntilIdle(); |
Pavol Marko | d69d430 | 2018-02-01 10:08:41 | [diff] [blame] | 601 | |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 602 | StartNetworkCertLoader(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 603 | task_environment_.RunUntilIdle(); |
Pavol Marko | d69d430 | 2018-02-01 10:08:41 | [diff] [blame] | 604 | |
| 605 | SetWifiState(shill::kStateOnline); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 606 | task_environment_.RunUntilIdle(); |
Pavol Marko | d69d430 | 2018-02-01 10:08:41 | [diff] [blame] | 607 | |
| 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 Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 619 | task_environment_.RunUntilIdle(); |
Pavol Marko | d69d430 | 2018-02-01 10:08:41 | [diff] [blame] | 620 | GetServiceProperty(shill::kEapCertIdProperty, &pkcs11_id); |
| 621 | EXPECT_EQ(test_cert_id_, pkcs11_id); |
| 622 | EXPECT_EQ(0, network_properties_changed_count_); |
emaxx | 98181cd | 2015-11-17 18:08:12 | [diff] [blame] | 623 | } |
| 624 | |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 625 | TEST_F(ClientCertResolverTest, UserPolicyUsesSystemToken) { |
| 626 | SetupTestCertInSystemToken("client_1"); |
| 627 | SetupWifi(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 628 | task_environment_.RunUntilIdle(); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 629 | |
| 630 | SetupNetworkHandlers(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 631 | ASSERT_NO_FATAL_FAILURE( |
| 632 | SetupPolicyMatchingIssuerCN(::onc::ONC_SOURCE_USER_POLICY)); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 633 | task_environment_.RunUntilIdle(); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 634 | |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 635 | StartNetworkCertLoader(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 636 | task_environment_.RunUntilIdle(); |
Pavol Marko | a835cfa | 2019-02-18 12:38:34 | [diff] [blame] | 637 | ASSERT_EQ(1U, network_cert_loader_->client_certs().size()); |
| 638 | EXPECT_TRUE(network_cert_loader_->client_certs()[0].is_device_wide()); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 639 | |
| 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 | |
| 647 | TEST_F(ClientCertResolverTest, UserPolicyUsesSystemTokenSync) { |
| 648 | SetupTestCertInSystemToken("client_1"); |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 649 | StartNetworkCertLoader(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 650 | task_environment_.RunUntilIdle(); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 651 | |
| 652 | client_cert::ClientCertConfig client_cert_config; |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 653 | SetupCertificateConfigMatchingIssuerCN(::onc::ONC_SOURCE_USER_POLICY, |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 654 | &client_cert_config); |
| 655 | |
| 656 | base::DictionaryValue shill_properties; |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 657 | ClientCertResolver::ResolveClientCertificateSync( |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 658 | 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 | |
| 665 | TEST_F(ClientCertResolverTest, DevicePolicyUsesSystemToken) { |
| 666 | SetupTestCertInSystemToken("client_1"); |
| 667 | SetupWifi(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 668 | task_environment_.RunUntilIdle(); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 669 | |
| 670 | SetupNetworkHandlers(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 671 | ASSERT_NO_FATAL_FAILURE( |
| 672 | SetupPolicyMatchingIssuerCN(::onc::ONC_SOURCE_USER_POLICY)); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 673 | task_environment_.RunUntilIdle(); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 674 | |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 675 | StartNetworkCertLoader(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 676 | task_environment_.RunUntilIdle(); |
Pavol Marko | a835cfa | 2019-02-18 12:38:34 | [diff] [blame] | 677 | ASSERT_EQ(1U, network_cert_loader_->client_certs().size()); |
| 678 | EXPECT_TRUE(network_cert_loader_->client_certs()[0].is_device_wide()); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 679 | |
| 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 | |
| 687 | TEST_F(ClientCertResolverTest, DevicePolicyUsesSystemTokenSync) { |
| 688 | SetupTestCertInSystemToken("client_1"); |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 689 | StartNetworkCertLoader(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 690 | task_environment_.RunUntilIdle(); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 691 | |
| 692 | client_cert::ClientCertConfig client_cert_config; |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 693 | SetupCertificateConfigMatchingIssuerCN(::onc::ONC_SOURCE_DEVICE_POLICY, |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 694 | &client_cert_config); |
| 695 | |
| 696 | base::DictionaryValue shill_properties; |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 697 | ClientCertResolver::ResolveClientCertificateSync( |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 698 | 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 | |
| 705 | TEST_F(ClientCertResolverTest, DevicePolicyDoesNotUseUserToken) { |
| 706 | SetupTestCerts("client_1", false /* do not import the issuer */); |
| 707 | SetupWifi(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 708 | task_environment_.RunUntilIdle(); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 709 | |
| 710 | SetupNetworkHandlers(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 711 | ASSERT_NO_FATAL_FAILURE( |
| 712 | SetupPolicyMatchingIssuerCN(::onc::ONC_SOURCE_DEVICE_POLICY)); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 713 | task_environment_.RunUntilIdle(); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 714 | |
| 715 | network_properties_changed_count_ = 0; |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 716 | StartNetworkCertLoader(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 717 | task_environment_.RunUntilIdle(); |
Pavol Marko | a835cfa | 2019-02-18 12:38:34 | [diff] [blame] | 718 | ASSERT_EQ(1U, network_cert_loader_->client_certs().size()); |
| 719 | EXPECT_FALSE(network_cert_loader_->client_certs()[0].is_device_wide()); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 720 | |
| 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 | |
| 729 | TEST_F(ClientCertResolverTest, DevicePolicyDoesNotUseUserTokenSync) { |
| 730 | SetupTestCerts("client_1", false /* do not import the issuer */); |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 731 | StartNetworkCertLoader(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 732 | task_environment_.RunUntilIdle(); |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 733 | |
| 734 | client_cert::ClientCertConfig client_cert_config; |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 735 | SetupCertificateConfigMatchingIssuerCN(::onc::ONC_SOURCE_DEVICE_POLICY, |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 736 | &client_cert_config); |
| 737 | |
| 738 | base::DictionaryValue shill_properties; |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 739 | ClientCertResolver::ResolveClientCertificateSync( |
pmarko | 93bc5d7 | 2017-04-27 10:58:28 | [diff] [blame] | 740 | 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 | |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 747 | TEST_F(ClientCertResolverTest, PopulateIdentityFromCert) { |
| 748 | SetupTestCerts("client_3", true /* import issuer */); |
| 749 | SetupWifi(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 750 | task_environment_.RunUntilIdle(); |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 751 | |
| 752 | SetupNetworkHandlers(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 753 | ASSERT_NO_FATAL_FAILURE(SetupPolicyMatchingIssuerPEM( |
| 754 | ::onc::ONC_SOURCE_USER_POLICY, "${CERT_SAN_EMAIL}")); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 755 | task_environment_.RunUntilIdle(); |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 756 | |
| 757 | network_properties_changed_count_ = 0; |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 758 | StartNetworkCertLoader(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 759 | task_environment_.RunUntilIdle(); |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 760 | |
| 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 Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 771 | ASSERT_NO_FATAL_FAILURE(SetupPolicyMatchingIssuerPEM( |
| 772 | ::onc::ONC_SOURCE_USER_POLICY, "upn-${CERT_SAN_UPN}-suffix")); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 773 | task_environment_.RunUntilIdle(); |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 774 | |
| 775 | GetServiceProperty(shill::kEapIdentityProperty, &identity); |
| 776 | EXPECT_EQ("[email protected]", identity); |
| 777 | EXPECT_EQ(2, network_properties_changed_count_); |
Pavol Marko | 75f1569b | 2018-04-24 14:01:21 | [diff] [blame] | 778 | |
| 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 Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 781 | ASSERT_NO_FATAL_FAILURE(SetupPolicyMatchingIssuerPEM( |
| 782 | ::onc::ONC_SOURCE_USER_POLICY, |
| 783 | "subject-cn-${CERT_SUBJECT_COMMON_NAME}-suffix")); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 784 | task_environment_.RunUntilIdle(); |
Pavol Marko | 75f1569b | 2018-04-24 14:01:21 | [diff] [blame] | 785 | |
| 786 | GetServiceProperty(shill::kEapIdentityProperty, &identity); |
| 787 | EXPECT_EQ("subject-cn-Client Cert F-suffix", identity); |
| 788 | EXPECT_EQ(3, network_properties_changed_count_); |
cernekee | 969c512 | 2016-03-03 19:28:31 | [diff] [blame] | 789 | } |
| 790 | |
Pavol Marko | 75afb40 | 2017-11-07 09:23:40 | [diff] [blame] | 791 | // Test for crbug.com/781276. A notification which results in no networks to be |
| 792 | // resolved should not alter the state of IsAnyResolveTaskRunning(). |
| 793 | TEST_F(ClientCertResolverTest, TestResolveTaskQueued) { |
| 794 | // Set up ClientCertResolver and let it run initially |
| 795 | SetupTestCerts("client_1", true /* import issuer */); |
Pavol Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 796 | StartNetworkCertLoader(); |
Pavol Marko | 75afb40 | 2017-11-07 09:23:40 | [diff] [blame] | 797 | SetupWifi(); |
| 798 | SetupNetworkHandlers(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 799 | ASSERT_NO_FATAL_FAILURE( |
| 800 | SetupPolicyMatchingIssuerPEM(::onc::ONC_SOURCE_USER_POLICY, "")); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 801 | task_environment_.RunUntilIdle(); |
Pavol Marko | 75afb40 | 2017-11-07 09:23:40 | [diff] [blame] | 802 | |
| 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 Marko | 5006c4c | 2018-10-09 12:58:10 | [diff] [blame] | 814 | static_cast<NetworkCertLoader::Observer*>(client_cert_resolver_.get()) |
Pavol Marko | a835cfa | 2019-02-18 12:38:34 | [diff] [blame] | 815 | ->OnCertificatesLoaded(); |
Pavol Marko | 75afb40 | 2017-11-07 09:23:40 | [diff] [blame] | 816 | EXPECT_TRUE(client_cert_resolver_->IsAnyResolveTaskRunning()); |
| 817 | |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 818 | task_environment_.RunUntilIdle(); |
Pavol Marko | 75afb40 | 2017-11-07 09:23:40 | [diff] [blame] | 819 | 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 Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 827 | // 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. |
| 831 | TEST_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 Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 849 | task_environment_.RunUntilIdle(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 850 | StartNetworkCertLoader(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 851 | task_environment_.RunUntilIdle(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 852 | SetupNetworkHandlers(); |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 853 | task_environment_.RunUntilIdle(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 854 | |
| 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 Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 862 | task_environment_.RunUntilIdle(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 863 | |
| 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 Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 879 | task_environment_.GetMainThreadTaskRunner(), test_nsscertdb_.get()); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 880 | 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 Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 885 | task_environment_.RunUntilIdle(); |
Pavol Marko | 0b3fedd | 2018-10-29 11:57:20 | [diff] [blame] | 886 | |
| 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] | 72b3a7e | 2013-08-13 15:30:04 | [diff] [blame] | 904 | } // namespace chromeos |