Some additional network settings cleanup
[chromium-blink-merge.git] / chromeos / network / network_cert_migrator_unittest.cc
blob88dec4f6efcc6c3807815b63b949cc24bb4ded50
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.
5 #include "chromeos/network/network_cert_migrator.h"
7 #include <cert.h>
9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "chromeos/cert_loader.h"
14 #include "chromeos/dbus/dbus_thread_manager.h"
15 #include "chromeos/dbus/shill_profile_client.h"
16 #include "chromeos/dbus/shill_service_client.h"
17 #include "chromeos/network/network_state_handler.h"
18 #include "chromeos/tpm_token_loader.h"
19 #include "crypto/nss_util_internal.h"
20 #include "crypto/scoped_test_nss_chromeos_user.h"
21 #include "net/base/crypto_module.h"
22 #include "net/base/net_errors.h"
23 #include "net/base/test_data_directory.h"
24 #include "net/cert/nss_cert_database_chromeos.h"
25 #include "net/cert/x509_certificate.h"
26 #include "net/test/cert_test_util.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "third_party/cros_system_api/dbus/service_constants.h"
30 namespace chromeos {
32 namespace {
34 const char* kWifiStub = "wifi_stub";
35 const char* kEthernetEapStub = "ethernet_eap_stub";
36 const char* kVPNStub = "vpn_stub";
37 const char* kNSSNickname = "nss_nickname";
38 const char* kFakePEM = "pem";
39 const char* kProfile = "/profile/profile1";
41 } // namespace
43 class NetworkCertMigratorTest : public testing::Test {
44 public:
45 NetworkCertMigratorTest() : service_test_(NULL),
46 user_("user_hash") {
48 virtual ~NetworkCertMigratorTest() {}
50 virtual void SetUp() OVERRIDE {
51 // Initialize NSS db for the user.
52 ASSERT_TRUE(user_.constructed_successfully());
53 user_.FinishInit();
54 test_nssdb_.reset(new net::NSSCertDatabaseChromeOS(
55 crypto::GetPublicSlotForChromeOSUser(user_.username_hash()),
56 crypto::GetPrivateSlotForChromeOSUser(
57 user_.username_hash(),
58 base::Callback<void(crypto::ScopedPK11Slot)>())));
59 test_nssdb_->SetSlowTaskRunnerForTest(message_loop_.message_loop_proxy());
61 DBusThreadManager::Initialize();
62 service_test_ =
63 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
64 DBusThreadManager::Get()
65 ->GetShillProfileClient()
66 ->GetTestInterface()
67 ->AddProfile(kProfile, "" /* userhash */);
68 base::RunLoop().RunUntilIdle();
69 service_test_->ClearServices();
70 base::RunLoop().RunUntilIdle();
72 CertLoader::Initialize();
73 CertLoader* cert_loader_ = CertLoader::Get();
74 cert_loader_->StartWithNSSDB(test_nssdb_.get());
77 virtual void TearDown() OVERRIDE {
78 network_cert_migrator_.reset();
79 network_state_handler_.reset();
80 CertLoader::Shutdown();
81 DBusThreadManager::Shutdown();
82 CleanupTestCert();
85 protected:
86 void SetupTestCACert() {
87 scoped_refptr<net::X509Certificate> cert_wo_nickname =
88 net::CreateCertificateListFromFile(net::GetTestCertsDirectory(),
89 "eku-test-root.pem",
90 net::X509Certificate::FORMAT_AUTO)
91 .back();
92 net::X509Certificate::GetPEMEncoded(cert_wo_nickname->os_cert_handle(),
93 &test_ca_cert_pem_);
94 std::string der_encoded;
95 net::X509Certificate::GetDEREncoded(cert_wo_nickname->os_cert_handle(),
96 &der_encoded);
97 cert_wo_nickname = NULL;
99 test_ca_cert_ = net::X509Certificate::CreateFromBytesWithNickname(
100 der_encoded.data(), der_encoded.size(), kNSSNickname);
101 net::CertificateList cert_list;
102 cert_list.push_back(test_ca_cert_);
103 net::NSSCertDatabase::ImportCertFailureList failures;
104 EXPECT_TRUE(test_nssdb_->ImportCACerts(
105 cert_list, net::NSSCertDatabase::TRUST_DEFAULT, &failures));
106 ASSERT_TRUE(failures.empty()) << net::ErrorToString(failures[0].net_error);
109 void SetupTestClientCert() {
110 std::string pkcs12_data;
111 ASSERT_TRUE(base::ReadFileToString(
112 net::GetTestCertsDirectory().Append("websocket_client_cert.p12"),
113 &pkcs12_data));
115 net::CertificateList client_cert_list;
116 scoped_refptr<net::CryptoModule> module(net::CryptoModule::CreateFromHandle(
117 test_nssdb_->GetPrivateSlot().get()));
118 ASSERT_EQ(net::OK,
119 test_nssdb_->ImportFromPKCS12(module.get(),
120 pkcs12_data,
121 base::string16(),
122 false,
123 &client_cert_list));
124 ASSERT_TRUE(!client_cert_list.empty());
125 test_client_cert_ = client_cert_list[0];
127 int slot_id = -1;
128 test_client_cert_pkcs11_id_ = CertLoader::GetPkcs11IdAndSlotForCert(
129 *test_client_cert_, &slot_id);
130 ASSERT_FALSE(test_client_cert_pkcs11_id_.empty());
131 ASSERT_NE(-1, slot_id);
132 test_client_cert_slot_id_ = base::IntToString(slot_id);
135 void SetupNetworkHandlers() {
136 network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
137 network_cert_migrator_.reset(new NetworkCertMigrator);
138 network_cert_migrator_->Init(network_state_handler_.get());
141 void AddService(const std::string& network_id,
142 const std::string& type,
143 const std::string& state) {
144 service_test_->AddService(network_id /* service_path */,
145 network_id /* guid */,
146 network_id /* name */,
147 type,
148 state,
149 true /* add_to_visible */);
151 // Ensure that the service appears as 'configured', i.e. is associated to a
152 // Shill profile.
153 service_test_->SetServiceProperty(
154 network_id, shill::kProfileProperty, base::StringValue(kProfile));
157 void SetupWifiWithNss() {
158 AddService(kWifiStub, shill::kTypeWifi, shill::kStateOnline);
159 service_test_->SetServiceProperty(kWifiStub,
160 shill::kEapCaCertNssProperty,
161 base::StringValue(kNSSNickname));
164 void SetupNetworkWithEapCertId(bool wifi, const std::string& cert_id) {
165 std::string type = wifi ? shill::kTypeWifi: shill::kTypeEthernetEap;
166 std::string name = wifi ? kWifiStub : kEthernetEapStub;
167 AddService(name, type, shill::kStateOnline);
168 service_test_->SetServiceProperty(
169 name, shill::kEapCertIdProperty, base::StringValue(cert_id));
170 service_test_->SetServiceProperty(
171 name, shill::kEapKeyIdProperty, base::StringValue(cert_id));
173 if (wifi) {
174 service_test_->SetServiceProperty(
175 name,
176 shill::kSecurityProperty,
177 base::StringValue(shill::kSecurity8021x));
181 void GetEapCertId(bool wifi, std::string* cert_id) {
182 cert_id->clear();
184 std::string name = wifi ? kWifiStub : kEthernetEapStub;
185 const base::DictionaryValue* properties =
186 service_test_->GetServiceProperties(name);
187 properties->GetStringWithoutPathExpansion(shill::kEapCertIdProperty,
188 cert_id);
191 void SetupVpnWithCertId(bool open_vpn,
192 const std::string& slot_id,
193 const std::string& pkcs11_id) {
194 AddService(kVPNStub, shill::kTypeVPN, shill::kStateIdle);
195 base::DictionaryValue provider;
196 if (open_vpn) {
197 provider.SetStringWithoutPathExpansion(shill::kTypeProperty,
198 shill::kProviderOpenVpn);
199 provider.SetStringWithoutPathExpansion(
200 shill::kOpenVPNClientCertIdProperty, pkcs11_id);
201 } else {
202 provider.SetStringWithoutPathExpansion(shill::kTypeProperty,
203 shill::kProviderL2tpIpsec);
204 provider.SetStringWithoutPathExpansion(
205 shill::kL2tpIpsecClientCertSlotProperty, slot_id);
206 provider.SetStringWithoutPathExpansion(
207 shill::kL2tpIpsecClientCertIdProperty, pkcs11_id);
209 service_test_->SetServiceProperty(
210 kVPNStub, shill::kProviderProperty, provider);
213 void GetVpnCertId(bool open_vpn,
214 std::string* slot_id,
215 std::string* pkcs11_id) {
216 slot_id->clear();
217 pkcs11_id->clear();
219 const base::DictionaryValue* properties =
220 service_test_->GetServiceProperties(kVPNStub);
221 ASSERT_TRUE(properties);
222 const base::DictionaryValue* provider = NULL;
223 properties->GetDictionaryWithoutPathExpansion(shill::kProviderProperty,
224 &provider);
225 if (!provider)
226 return;
227 if (open_vpn) {
228 provider->GetStringWithoutPathExpansion(
229 shill::kOpenVPNClientCertIdProperty, pkcs11_id);
230 } else {
231 provider->GetStringWithoutPathExpansion(
232 shill::kL2tpIpsecClientCertSlotProperty, slot_id);
233 provider->GetStringWithoutPathExpansion(
234 shill::kL2tpIpsecClientCertIdProperty, pkcs11_id);
238 void GetEapCACertProperties(std::string* nss_nickname, std::string* ca_pem) {
239 nss_nickname->clear();
240 ca_pem->clear();
241 const base::DictionaryValue* properties =
242 service_test_->GetServiceProperties(kWifiStub);
243 properties->GetStringWithoutPathExpansion(shill::kEapCaCertNssProperty,
244 nss_nickname);
245 const base::ListValue* ca_pems = NULL;
246 properties->GetListWithoutPathExpansion(shill::kEapCaCertPemProperty,
247 &ca_pems);
248 if (ca_pems && !ca_pems->empty())
249 ca_pems->GetString(0, ca_pem);
252 void SetupVpnWithNss(bool open_vpn) {
253 AddService(kVPNStub, shill::kTypeVPN, shill::kStateIdle);
254 base::DictionaryValue provider;
255 const char* nss_property = open_vpn ? shill::kOpenVPNCaCertNSSProperty
256 : shill::kL2tpIpsecCaCertNssProperty;
257 provider.SetStringWithoutPathExpansion(nss_property, kNSSNickname);
258 service_test_->SetServiceProperty(
259 kVPNStub, shill::kProviderProperty, provider);
262 void GetVpnCACertProperties(bool open_vpn,
263 std::string* nss_nickname,
264 std::string* ca_pem) {
265 nss_nickname->clear();
266 ca_pem->clear();
267 const base::DictionaryValue* properties =
268 service_test_->GetServiceProperties(kVPNStub);
269 const base::DictionaryValue* provider = NULL;
270 properties->GetDictionaryWithoutPathExpansion(shill::kProviderProperty,
271 &provider);
272 if (!provider)
273 return;
274 const char* nss_property = open_vpn ? shill::kOpenVPNCaCertNSSProperty
275 : shill::kL2tpIpsecCaCertNssProperty;
276 provider->GetStringWithoutPathExpansion(nss_property, nss_nickname);
277 const base::ListValue* ca_pems = NULL;
278 const char* pem_property = open_vpn ? shill::kOpenVPNCaCertPemProperty
279 : shill::kL2tpIpsecCaCertPemProperty;
280 provider->GetListWithoutPathExpansion(pem_property, &ca_pems);
281 if (ca_pems && !ca_pems->empty())
282 ca_pems->GetString(0, ca_pem);
285 ShillServiceClient::TestInterface* service_test_;
286 scoped_refptr<net::X509Certificate> test_ca_cert_;
287 scoped_refptr<net::X509Certificate> test_client_cert_;
288 std::string test_client_cert_pkcs11_id_;
289 std::string test_client_cert_slot_id_;
290 std::string test_ca_cert_pem_;
291 base::MessageLoop message_loop_;
293 private:
294 void CleanupTestCert() {
295 if (test_ca_cert_.get())
296 ASSERT_TRUE(test_nssdb_->DeleteCertAndKey(test_ca_cert_.get()));
298 if (test_client_cert_.get())
299 ASSERT_TRUE(test_nssdb_->DeleteCertAndKey(test_client_cert_.get()));
302 scoped_ptr<NetworkStateHandler> network_state_handler_;
303 scoped_ptr<NetworkCertMigrator> network_cert_migrator_;
304 crypto::ScopedTestNSSChromeOSUser user_;
305 scoped_ptr<net::NSSCertDatabaseChromeOS> test_nssdb_;
307 DISALLOW_COPY_AND_ASSIGN(NetworkCertMigratorTest);
310 TEST_F(NetworkCertMigratorTest, MigrateNssOnInitialization) {
311 // Add a new network for migration before the handlers are initialized.
312 SetupWifiWithNss();
313 SetupTestCACert();
314 SetupNetworkHandlers();
316 base::RunLoop().RunUntilIdle();
317 std::string nss_nickname, ca_pem;
318 GetEapCACertProperties(&nss_nickname, &ca_pem);
319 EXPECT_TRUE(nss_nickname.empty());
320 EXPECT_EQ(test_ca_cert_pem_, ca_pem);
323 TEST_F(NetworkCertMigratorTest, MigrateNssOnNetworkAppearance) {
324 SetupTestCACert();
325 SetupNetworkHandlers();
326 base::RunLoop().RunUntilIdle();
328 // Add a new network for migration after the handlers are initialized.
329 SetupWifiWithNss();
331 base::RunLoop().RunUntilIdle();
332 std::string nss_nickname, ca_pem;
333 GetEapCACertProperties(&nss_nickname, &ca_pem);
334 EXPECT_TRUE(nss_nickname.empty());
335 EXPECT_EQ(test_ca_cert_pem_, ca_pem);
338 TEST_F(NetworkCertMigratorTest, DoNotMigrateNssIfPemSet) {
339 // Add a new network with an already set PEM property.
340 SetupWifiWithNss();
341 base::ListValue ca_pems;
342 ca_pems.AppendString(kFakePEM);
343 service_test_->SetServiceProperty(
344 kWifiStub, shill::kEapCaCertPemProperty, ca_pems);
346 SetupTestCACert();
347 SetupNetworkHandlers();
348 base::RunLoop().RunUntilIdle();
350 std::string nss_nickname, ca_pem;
351 GetEapCACertProperties(&nss_nickname, &ca_pem);
352 EXPECT_TRUE(nss_nickname.empty());
353 EXPECT_EQ(kFakePEM, ca_pem);
356 TEST_F(NetworkCertMigratorTest, MigrateNssOpenVpn) {
357 // Add a new network for migration before the handlers are initialized.
358 SetupVpnWithNss(true /* OpenVPN */);
360 SetupTestCACert();
361 SetupNetworkHandlers();
363 base::RunLoop().RunUntilIdle();
364 std::string nss_nickname, ca_pem;
365 GetVpnCACertProperties(true /* OpenVPN */, &nss_nickname, &ca_pem);
366 EXPECT_TRUE(nss_nickname.empty());
367 EXPECT_EQ(test_ca_cert_pem_, ca_pem);
370 TEST_F(NetworkCertMigratorTest, MigrateNssIpsecVpn) {
371 // Add a new network for migration before the handlers are initialized.
372 SetupVpnWithNss(false /* not OpenVPN */);
374 SetupTestCACert();
375 SetupNetworkHandlers();
377 base::RunLoop().RunUntilIdle();
378 std::string nss_nickname, ca_pem;
379 GetVpnCACertProperties(false /* not OpenVPN */, &nss_nickname, &ca_pem);
380 EXPECT_TRUE(nss_nickname.empty());
381 EXPECT_EQ(test_ca_cert_pem_, ca_pem);
384 TEST_F(NetworkCertMigratorTest, MigrateEapCertIdNoMatchingCert) {
385 SetupTestClientCert();
386 SetupNetworkHandlers();
387 base::RunLoop().RunUntilIdle();
389 // Add a new network for migration after the handlers are initialized.
390 SetupNetworkWithEapCertId(true /* wifi */, "unknown pkcs11 id");
392 base::RunLoop().RunUntilIdle();
393 // Since the PKCS11 ID is unknown, the certificate configuration will be
394 // cleared.
395 std::string cert_id;
396 GetEapCertId(true /* wifi */, &cert_id);
397 EXPECT_EQ(std::string(), cert_id);
400 TEST_F(NetworkCertMigratorTest, MigrateEapCertIdNoSlotId) {
401 SetupTestClientCert();
402 SetupNetworkHandlers();
403 base::RunLoop().RunUntilIdle();
405 // Add a new network for migration after the handlers are initialized.
406 SetupNetworkWithEapCertId(true /* wifi */, test_client_cert_pkcs11_id_);
408 base::RunLoop().RunUntilIdle();
410 std::string cert_id;
411 GetEapCertId(true /* wifi */, &cert_id);
412 std::string expected_cert_id =
413 test_client_cert_slot_id_ + ":" + test_client_cert_pkcs11_id_;
414 EXPECT_EQ(expected_cert_id, cert_id);
417 TEST_F(NetworkCertMigratorTest, MigrateWifiEapCertIdWrongSlotId) {
418 SetupTestClientCert();
419 SetupNetworkHandlers();
420 base::RunLoop().RunUntilIdle();
422 // Add a new network for migration after the handlers are initialized.
423 SetupNetworkWithEapCertId(true /* wifi */,
424 "123:" + test_client_cert_pkcs11_id_);
426 base::RunLoop().RunUntilIdle();
428 std::string cert_id;
429 GetEapCertId(true /* wifi */, &cert_id);
430 std::string expected_cert_id =
431 test_client_cert_slot_id_ + ":" + test_client_cert_pkcs11_id_;
432 EXPECT_EQ(expected_cert_id, cert_id);
435 TEST_F(NetworkCertMigratorTest, DoNotChangeEapCertIdWithCorrectSlotId) {
436 SetupTestClientCert();
437 SetupNetworkHandlers();
438 base::RunLoop().RunUntilIdle();
440 std::string expected_cert_id =
441 test_client_cert_slot_id_ + ":" + test_client_cert_pkcs11_id_;
443 // Add a new network for migration after the handlers are initialized.
444 SetupNetworkWithEapCertId(true /* wifi */, expected_cert_id);
446 base::RunLoop().RunUntilIdle();
448 std::string cert_id;
449 GetEapCertId(true /* wifi */, &cert_id);
450 EXPECT_EQ(expected_cert_id, cert_id);
453 TEST_F(NetworkCertMigratorTest, IgnoreOpenVPNCertId) {
454 SetupTestClientCert();
455 SetupNetworkHandlers();
456 base::RunLoop().RunUntilIdle();
458 const char kPkcs11Id[] = "any slot id";
460 // Add a new network for migration after the handlers are initialized.
461 SetupVpnWithCertId(
462 true /* OpenVPN */, std::string() /* no slot id */, kPkcs11Id);
464 base::RunLoop().RunUntilIdle();
466 std::string pkcs11_id;
467 std::string unused_slot_id;
468 GetVpnCertId(true /* OpenVPN */, &unused_slot_id, &pkcs11_id);
469 EXPECT_EQ(kPkcs11Id, pkcs11_id);
472 TEST_F(NetworkCertMigratorTest, MigrateEthernetEapCertIdWrongSlotId) {
473 SetupTestClientCert();
474 SetupNetworkHandlers();
475 base::RunLoop().RunUntilIdle();
477 // Add a new network for migration after the handlers are initialized.
478 SetupNetworkWithEapCertId(
479 false /* ethernet */, "123:" + test_client_cert_pkcs11_id_);
481 base::RunLoop().RunUntilIdle();
483 std::string cert_id;
484 GetEapCertId(false /* ethernet */, &cert_id);
485 std::string expected_cert_id =
486 test_client_cert_slot_id_ + ":" + test_client_cert_pkcs11_id_;
487 EXPECT_EQ(expected_cert_id, cert_id);
490 TEST_F(NetworkCertMigratorTest, MigrateIpsecCertIdWrongSlotId) {
491 SetupTestClientCert();
492 SetupNetworkHandlers();
493 base::RunLoop().RunUntilIdle();
495 // Add a new network for migration after the handlers are initialized.
496 SetupVpnWithCertId(false /* IPsec */, "123", test_client_cert_pkcs11_id_);
498 base::RunLoop().RunUntilIdle();
500 std::string pkcs11_id;
501 std::string slot_id;
502 GetVpnCertId(false /* IPsec */, &slot_id, &pkcs11_id);
503 EXPECT_EQ(test_client_cert_pkcs11_id_, pkcs11_id);
504 EXPECT_EQ(test_client_cert_slot_id_, slot_id);
507 } // namespace chromeos