Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chromeos / network / network_cert_migrator_unittest.cc
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
5 #include "chromeos/network/network_cert_migrator.h"
6
7 #include <cert.h>
8
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"
29
30 // http://crbug.com/418369
31 #ifdef NDEBUG
32
33 namespace chromeos {
34
35 namespace {
36
37 const char* kWifiStub = "wifi_stub";
38 const char* kEthernetEapStub = "ethernet_eap_stub";
39 const char* kVPNStub = "vpn_stub";
40 const char* kNSSNickname = "nss_nickname";
41 const char* kFakePEM = "pem";
42 const char* kProfile = "/profile/profile1";
43
44 }  // namespace
45
46 class NetworkCertMigratorTest : public testing::Test {
47  public:
48   NetworkCertMigratorTest() : service_test_(NULL),
49                               user_("user_hash") {
50   }
51   virtual ~NetworkCertMigratorTest() {}
52
53   virtual void SetUp() override {
54     // Initialize NSS db for the user.
55     ASSERT_TRUE(user_.constructed_successfully());
56     user_.FinishInit();
57     test_nssdb_.reset(new net::NSSCertDatabaseChromeOS(
58         crypto::GetPublicSlotForChromeOSUser(user_.username_hash()),
59         crypto::GetPrivateSlotForChromeOSUser(
60             user_.username_hash(),
61             base::Callback<void(crypto::ScopedPK11Slot)>())));
62     test_nssdb_->SetSlowTaskRunnerForTest(message_loop_.message_loop_proxy());
63
64     DBusThreadManager::Initialize();
65     service_test_ =
66         DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
67     DBusThreadManager::Get()
68         ->GetShillProfileClient()
69         ->GetTestInterface()
70         ->AddProfile(kProfile, "" /* userhash */);
71     base::RunLoop().RunUntilIdle();
72     service_test_->ClearServices();
73     base::RunLoop().RunUntilIdle();
74
75     CertLoader::Initialize();
76     CertLoader* cert_loader_ = CertLoader::Get();
77     cert_loader_->StartWithNSSDB(test_nssdb_.get());
78   }
79
80   virtual void TearDown() override {
81     network_cert_migrator_.reset();
82     network_state_handler_.reset();
83     CertLoader::Shutdown();
84     DBusThreadManager::Shutdown();
85     CleanupTestCert();
86   }
87
88  protected:
89   void SetupTestCACert() {
90     scoped_refptr<net::X509Certificate> cert_wo_nickname =
91         net::CreateCertificateListFromFile(net::GetTestCertsDirectory(),
92                                            "eku-test-root.pem",
93                                            net::X509Certificate::FORMAT_AUTO)
94             .back();
95     net::X509Certificate::GetPEMEncoded(cert_wo_nickname->os_cert_handle(),
96                                         &test_ca_cert_pem_);
97     std::string der_encoded;
98     net::X509Certificate::GetDEREncoded(cert_wo_nickname->os_cert_handle(),
99                                         &der_encoded);
100     cert_wo_nickname = NULL;
101
102     test_ca_cert_ = net::X509Certificate::CreateFromBytesWithNickname(
103         der_encoded.data(), der_encoded.size(), kNSSNickname);
104     net::CertificateList cert_list;
105     cert_list.push_back(test_ca_cert_);
106     net::NSSCertDatabase::ImportCertFailureList failures;
107     EXPECT_TRUE(test_nssdb_->ImportCACerts(
108         cert_list, net::NSSCertDatabase::TRUST_DEFAULT, &failures));
109     ASSERT_TRUE(failures.empty()) << net::ErrorToString(failures[0].net_error);
110   }
111
112   void SetupTestClientCert() {
113     std::string pkcs12_data;
114     ASSERT_TRUE(base::ReadFileToString(
115         net::GetTestCertsDirectory().Append("websocket_client_cert.p12"),
116         &pkcs12_data));
117
118     net::CertificateList client_cert_list;
119     scoped_refptr<net::CryptoModule> module(net::CryptoModule::CreateFromHandle(
120         test_nssdb_->GetPrivateSlot().get()));
121     ASSERT_EQ(net::OK,
122               test_nssdb_->ImportFromPKCS12(module.get(),
123                                             pkcs12_data,
124                                             base::string16(),
125                                             false,
126                                             &client_cert_list));
127     ASSERT_TRUE(!client_cert_list.empty());
128     test_client_cert_ = client_cert_list[0];
129
130     int slot_id = -1;
131     test_client_cert_pkcs11_id_ = CertLoader::GetPkcs11IdAndSlotForCert(
132         *test_client_cert_, &slot_id);
133     ASSERT_FALSE(test_client_cert_pkcs11_id_.empty());
134     ASSERT_NE(-1, slot_id);
135     test_client_cert_slot_id_ = base::IntToString(slot_id);
136   }
137
138   void SetupNetworkHandlers() {
139     network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
140     network_cert_migrator_.reset(new NetworkCertMigrator);
141     network_cert_migrator_->Init(network_state_handler_.get());
142   }
143
144   void AddService(const std::string& network_id,
145                   const std::string& type,
146                   const std::string& state) {
147     service_test_->AddService(network_id /* service_path */,
148                               network_id /* guid */,
149                               network_id /* name */,
150                               type,
151                               state,
152                               true /* add_to_visible */);
153
154     // Ensure that the service appears as 'configured', i.e. is associated to a
155     // Shill profile.
156     service_test_->SetServiceProperty(
157         network_id, shill::kProfileProperty, base::StringValue(kProfile));
158   }
159
160   void SetupWifiWithNss() {
161     AddService(kWifiStub, shill::kTypeWifi, shill::kStateOnline);
162     service_test_->SetServiceProperty(kWifiStub,
163                                       shill::kEapCaCertNssProperty,
164                                       base::StringValue(kNSSNickname));
165   }
166
167   void SetupNetworkWithEapCertId(bool wifi, const std::string& cert_id) {
168     std::string type = wifi ? shill::kTypeWifi: shill::kTypeEthernetEap;
169     std::string name = wifi ? kWifiStub : kEthernetEapStub;
170     AddService(name, type, shill::kStateOnline);
171     service_test_->SetServiceProperty(
172         name, shill::kEapCertIdProperty, base::StringValue(cert_id));
173     service_test_->SetServiceProperty(
174         name, shill::kEapKeyIdProperty, base::StringValue(cert_id));
175
176     if (wifi) {
177       service_test_->SetServiceProperty(
178           name,
179           shill::kSecurityProperty,
180           base::StringValue(shill::kSecurity8021x));
181     }
182   }
183
184   void GetEapCertId(bool wifi, std::string* cert_id) {
185     cert_id->clear();
186
187     std::string name = wifi ? kWifiStub : kEthernetEapStub;
188     const base::DictionaryValue* properties =
189         service_test_->GetServiceProperties(name);
190     properties->GetStringWithoutPathExpansion(shill::kEapCertIdProperty,
191                                               cert_id);
192   }
193
194   void SetupVpnWithCertId(bool open_vpn,
195                           const std::string& slot_id,
196                           const std::string& pkcs11_id) {
197     AddService(kVPNStub, shill::kTypeVPN, shill::kStateIdle);
198     base::DictionaryValue provider;
199     if (open_vpn) {
200       provider.SetStringWithoutPathExpansion(shill::kTypeProperty,
201                                              shill::kProviderOpenVpn);
202       provider.SetStringWithoutPathExpansion(
203           shill::kOpenVPNClientCertIdProperty, pkcs11_id);
204     } else {
205       provider.SetStringWithoutPathExpansion(shill::kTypeProperty,
206                                              shill::kProviderL2tpIpsec);
207       provider.SetStringWithoutPathExpansion(
208           shill::kL2tpIpsecClientCertSlotProperty, slot_id);
209       provider.SetStringWithoutPathExpansion(
210           shill::kL2tpIpsecClientCertIdProperty, pkcs11_id);
211     }
212     service_test_->SetServiceProperty(
213         kVPNStub, shill::kProviderProperty, provider);
214   }
215
216   void GetVpnCertId(bool open_vpn,
217                     std::string* slot_id,
218                     std::string* pkcs11_id) {
219     slot_id->clear();
220     pkcs11_id->clear();
221
222     const base::DictionaryValue* properties =
223         service_test_->GetServiceProperties(kVPNStub);
224     ASSERT_TRUE(properties);
225     const base::DictionaryValue* provider = NULL;
226     properties->GetDictionaryWithoutPathExpansion(shill::kProviderProperty,
227                                                   &provider);
228     if (!provider)
229       return;
230     if (open_vpn) {
231       provider->GetStringWithoutPathExpansion(
232           shill::kOpenVPNClientCertIdProperty, pkcs11_id);
233     } else {
234       provider->GetStringWithoutPathExpansion(
235           shill::kL2tpIpsecClientCertSlotProperty, slot_id);
236       provider->GetStringWithoutPathExpansion(
237           shill::kL2tpIpsecClientCertIdProperty, pkcs11_id);
238     }
239   }
240
241   void GetEapCACertProperties(std::string* nss_nickname, std::string* ca_pem) {
242     nss_nickname->clear();
243     ca_pem->clear();
244     const base::DictionaryValue* properties =
245         service_test_->GetServiceProperties(kWifiStub);
246     properties->GetStringWithoutPathExpansion(shill::kEapCaCertNssProperty,
247                                               nss_nickname);
248     const base::ListValue* ca_pems = NULL;
249     properties->GetListWithoutPathExpansion(shill::kEapCaCertPemProperty,
250                                             &ca_pems);
251     if (ca_pems && !ca_pems->empty())
252       ca_pems->GetString(0, ca_pem);
253   }
254
255   void SetupVpnWithNss(bool open_vpn) {
256     AddService(kVPNStub, shill::kTypeVPN, shill::kStateIdle);
257     base::DictionaryValue provider;
258     const char* nss_property = open_vpn ? shill::kOpenVPNCaCertNSSProperty
259                                         : shill::kL2tpIpsecCaCertNssProperty;
260     provider.SetStringWithoutPathExpansion(nss_property, kNSSNickname);
261     service_test_->SetServiceProperty(
262         kVPNStub, shill::kProviderProperty, provider);
263   }
264
265   void GetVpnCACertProperties(bool open_vpn,
266                               std::string* nss_nickname,
267                               std::string* ca_pem) {
268     nss_nickname->clear();
269     ca_pem->clear();
270     const base::DictionaryValue* properties =
271         service_test_->GetServiceProperties(kVPNStub);
272     const base::DictionaryValue* provider = NULL;
273     properties->GetDictionaryWithoutPathExpansion(shill::kProviderProperty,
274                                                   &provider);
275     if (!provider)
276       return;
277     const char* nss_property = open_vpn ? shill::kOpenVPNCaCertNSSProperty
278                                         : shill::kL2tpIpsecCaCertNssProperty;
279     provider->GetStringWithoutPathExpansion(nss_property, nss_nickname);
280     const base::ListValue* ca_pems = NULL;
281     const char* pem_property = open_vpn ? shill::kOpenVPNCaCertPemProperty
282                                         : shill::kL2tpIpsecCaCertPemProperty;
283     provider->GetListWithoutPathExpansion(pem_property, &ca_pems);
284     if (ca_pems && !ca_pems->empty())
285       ca_pems->GetString(0, ca_pem);
286   }
287
288   ShillServiceClient::TestInterface* service_test_;
289   scoped_refptr<net::X509Certificate> test_ca_cert_;
290   scoped_refptr<net::X509Certificate> test_client_cert_;
291   std::string test_client_cert_pkcs11_id_;
292   std::string test_client_cert_slot_id_;
293   std::string test_ca_cert_pem_;
294   base::MessageLoop message_loop_;
295
296  private:
297   void CleanupTestCert() {
298     if (test_ca_cert_.get())
299       ASSERT_TRUE(test_nssdb_->DeleteCertAndKey(test_ca_cert_.get()));
300
301     if (test_client_cert_.get())
302       ASSERT_TRUE(test_nssdb_->DeleteCertAndKey(test_client_cert_.get()));
303   }
304
305   scoped_ptr<NetworkStateHandler> network_state_handler_;
306   scoped_ptr<NetworkCertMigrator> network_cert_migrator_;
307   crypto::ScopedTestNSSChromeOSUser user_;
308   scoped_ptr<net::NSSCertDatabaseChromeOS> test_nssdb_;
309
310   DISALLOW_COPY_AND_ASSIGN(NetworkCertMigratorTest);
311 };
312
313 TEST_F(NetworkCertMigratorTest, MigrateNssOnInitialization) {
314   // Add a new network for migration before the handlers are initialized.
315   SetupWifiWithNss();
316   SetupTestCACert();
317   SetupNetworkHandlers();
318
319   base::RunLoop().RunUntilIdle();
320   std::string nss_nickname, ca_pem;
321   GetEapCACertProperties(&nss_nickname, &ca_pem);
322   EXPECT_TRUE(nss_nickname.empty());
323   EXPECT_EQ(test_ca_cert_pem_, ca_pem);
324 }
325
326 TEST_F(NetworkCertMigratorTest, MigrateNssOnNetworkAppearance) {
327   SetupTestCACert();
328   SetupNetworkHandlers();
329   base::RunLoop().RunUntilIdle();
330
331   // Add a new network for migration after the handlers are initialized.
332   SetupWifiWithNss();
333
334   base::RunLoop().RunUntilIdle();
335   std::string nss_nickname, ca_pem;
336   GetEapCACertProperties(&nss_nickname, &ca_pem);
337   EXPECT_TRUE(nss_nickname.empty());
338   EXPECT_EQ(test_ca_cert_pem_, ca_pem);
339 }
340
341 TEST_F(NetworkCertMigratorTest, DoNotMigrateNssIfPemSet) {
342   // Add a new network with an already set PEM property.
343   SetupWifiWithNss();
344   base::ListValue ca_pems;
345   ca_pems.AppendString(kFakePEM);
346   service_test_->SetServiceProperty(
347       kWifiStub, shill::kEapCaCertPemProperty, ca_pems);
348
349   SetupTestCACert();
350   SetupNetworkHandlers();
351   base::RunLoop().RunUntilIdle();
352
353   std::string nss_nickname, ca_pem;
354   GetEapCACertProperties(&nss_nickname, &ca_pem);
355   EXPECT_TRUE(nss_nickname.empty());
356   EXPECT_EQ(kFakePEM, ca_pem);
357 }
358
359 TEST_F(NetworkCertMigratorTest, MigrateNssOpenVpn) {
360   // Add a new network for migration before the handlers are initialized.
361   SetupVpnWithNss(true /* OpenVPN */);
362
363   SetupTestCACert();
364   SetupNetworkHandlers();
365
366   base::RunLoop().RunUntilIdle();
367   std::string nss_nickname, ca_pem;
368   GetVpnCACertProperties(true /* OpenVPN */, &nss_nickname, &ca_pem);
369   EXPECT_TRUE(nss_nickname.empty());
370   EXPECT_EQ(test_ca_cert_pem_, ca_pem);
371 }
372
373 TEST_F(NetworkCertMigratorTest, MigrateNssIpsecVpn) {
374   // Add a new network for migration before the handlers are initialized.
375   SetupVpnWithNss(false /* not OpenVPN */);
376
377   SetupTestCACert();
378   SetupNetworkHandlers();
379
380   base::RunLoop().RunUntilIdle();
381   std::string nss_nickname, ca_pem;
382   GetVpnCACertProperties(false /* not OpenVPN */, &nss_nickname, &ca_pem);
383   EXPECT_TRUE(nss_nickname.empty());
384   EXPECT_EQ(test_ca_cert_pem_, ca_pem);
385 }
386
387 TEST_F(NetworkCertMigratorTest, MigrateEapCertIdNoMatchingCert) {
388   SetupTestClientCert();
389   SetupNetworkHandlers();
390   base::RunLoop().RunUntilIdle();
391
392   // Add a new network for migration after the handlers are initialized.
393   SetupNetworkWithEapCertId(true /* wifi */, "unknown pkcs11 id");
394
395   base::RunLoop().RunUntilIdle();
396   // Since the PKCS11 ID is unknown, the certificate configuration will be
397   // cleared.
398   std::string cert_id;
399   GetEapCertId(true /* wifi */, &cert_id);
400   EXPECT_EQ(std::string(), cert_id);
401 }
402
403 TEST_F(NetworkCertMigratorTest, MigrateEapCertIdNoSlotId) {
404   SetupTestClientCert();
405   SetupNetworkHandlers();
406   base::RunLoop().RunUntilIdle();
407
408   // Add a new network for migration after the handlers are initialized.
409   SetupNetworkWithEapCertId(true /* wifi */, test_client_cert_pkcs11_id_);
410
411   base::RunLoop().RunUntilIdle();
412
413   std::string cert_id;
414   GetEapCertId(true /* wifi */, &cert_id);
415   std::string expected_cert_id =
416       test_client_cert_slot_id_ + ":" + test_client_cert_pkcs11_id_;
417   EXPECT_EQ(expected_cert_id, cert_id);
418 }
419
420 TEST_F(NetworkCertMigratorTest, MigrateWifiEapCertIdWrongSlotId) {
421   SetupTestClientCert();
422   SetupNetworkHandlers();
423   base::RunLoop().RunUntilIdle();
424
425   // Add a new network for migration after the handlers are initialized.
426   SetupNetworkWithEapCertId(true /* wifi */,
427                             "123:" + test_client_cert_pkcs11_id_);
428
429   base::RunLoop().RunUntilIdle();
430
431   std::string cert_id;
432   GetEapCertId(true /* wifi */, &cert_id);
433   std::string expected_cert_id =
434       test_client_cert_slot_id_ + ":" + test_client_cert_pkcs11_id_;
435   EXPECT_EQ(expected_cert_id, cert_id);
436 }
437
438 TEST_F(NetworkCertMigratorTest, DoNotChangeEapCertIdWithCorrectSlotId) {
439   SetupTestClientCert();
440   SetupNetworkHandlers();
441   base::RunLoop().RunUntilIdle();
442
443   std::string expected_cert_id =
444       test_client_cert_slot_id_ + ":" + test_client_cert_pkcs11_id_;
445
446   // Add a new network for migration after the handlers are initialized.
447   SetupNetworkWithEapCertId(true /* wifi */, expected_cert_id);
448
449   base::RunLoop().RunUntilIdle();
450
451   std::string cert_id;
452   GetEapCertId(true /* wifi */, &cert_id);
453   EXPECT_EQ(expected_cert_id, cert_id);
454 }
455
456 TEST_F(NetworkCertMigratorTest, IgnoreOpenVPNCertId) {
457   SetupTestClientCert();
458   SetupNetworkHandlers();
459   base::RunLoop().RunUntilIdle();
460
461   const char kPkcs11Id[] = "any slot id";
462
463   // Add a new network for migration after the handlers are initialized.
464   SetupVpnWithCertId(
465       true /* OpenVPN */, std::string() /* no slot id */, kPkcs11Id);
466
467   base::RunLoop().RunUntilIdle();
468
469   std::string pkcs11_id;
470   std::string unused_slot_id;
471   GetVpnCertId(true /* OpenVPN */, &unused_slot_id, &pkcs11_id);
472   EXPECT_EQ(kPkcs11Id, pkcs11_id);
473 }
474
475 TEST_F(NetworkCertMigratorTest, MigrateEthernetEapCertIdWrongSlotId) {
476   SetupTestClientCert();
477   SetupNetworkHandlers();
478   base::RunLoop().RunUntilIdle();
479
480   // Add a new network for migration after the handlers are initialized.
481   SetupNetworkWithEapCertId(
482       false /* ethernet */, "123:" + test_client_cert_pkcs11_id_);
483
484   base::RunLoop().RunUntilIdle();
485
486   std::string cert_id;
487   GetEapCertId(false /* ethernet */, &cert_id);
488   std::string expected_cert_id =
489       test_client_cert_slot_id_ + ":" + test_client_cert_pkcs11_id_;
490   EXPECT_EQ(expected_cert_id, cert_id);
491 }
492
493 TEST_F(NetworkCertMigratorTest, MigrateIpsecCertIdWrongSlotId) {
494   SetupTestClientCert();
495   SetupNetworkHandlers();
496   base::RunLoop().RunUntilIdle();
497
498   // Add a new network for migration after the handlers are initialized.
499   SetupVpnWithCertId(false /* IPsec */, "123", test_client_cert_pkcs11_id_);
500
501   base::RunLoop().RunUntilIdle();
502
503   std::string pkcs11_id;
504   std::string slot_id;
505   GetVpnCertId(false /* IPsec */, &slot_id, &pkcs11_id);
506   EXPECT_EQ(test_client_cert_pkcs11_id_, pkcs11_id);
507   EXPECT_EQ(test_client_cert_slot_id_, slot_id);
508 }
509
510 }  // namespace chromeos
511
512 #endif