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"
9 #include "base/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/run_loop.h"
12 #include "chromeos/cert_loader.h"
13 #include "chromeos/dbus/dbus_thread_manager.h"
14 #include "chromeos/dbus/shill_service_client.h"
15 #include "chromeos/login/login_state.h"
16 #include "chromeos/network/network_state_handler.h"
17 #include "chromeos/tpm_token_loader.h"
18 #include "crypto/nss_util.h"
19 #include "net/base/crypto_module.h"
20 #include "net/base/net_errors.h"
21 #include "net/base/test_data_directory.h"
22 #include "net/cert/nss_cert_database.h"
23 #include "net/cert/x509_certificate.h"
24 #include "net/test/cert_test_util.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "third_party/cros_system_api/dbus/service_constants.h"
32 const char* kWifiStub
= "wifi_stub";
33 const char* kVPNStub
= "vpn_stub";
34 const char* kNSSNickname
= "nss_nickname";
35 const char* kFakePEM
= "pem";
39 class NetworkCertMigratorTest
: public testing::Test
{
41 NetworkCertMigratorTest() {}
42 virtual ~NetworkCertMigratorTest() {}
44 virtual void SetUp() OVERRIDE
{
45 ASSERT_TRUE(test_nssdb_
.is_open());
46 slot_
= net::NSSCertDatabase::GetInstance()->GetPublicModule();
47 ASSERT_TRUE(slot_
->os_module_handle());
49 LoginState::Initialize();
51 DBusThreadManager::InitializeWithStub();
53 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
54 message_loop_
.RunUntilIdle();
55 service_test_
->ClearServices();
56 message_loop_
.RunUntilIdle();
58 TPMTokenLoader::Initialize();
59 TPMTokenLoader
* tpm_token_loader
= TPMTokenLoader::Get();
60 tpm_token_loader
->InitializeTPMForTest();
61 tpm_token_loader
->SetCryptoTaskRunner(message_loop_
.message_loop_proxy());
63 CertLoader::Initialize();
64 CertLoader::Get()->SetSlowTaskRunnerForTest(
65 message_loop_
.message_loop_proxy());
68 virtual void TearDown() OVERRIDE
{
69 network_cert_migrator_
.reset();
70 network_state_handler_
.reset();
71 CertLoader::Shutdown();
72 TPMTokenLoader::Shutdown();
73 DBusThreadManager::Shutdown();
74 LoginState::Shutdown();
79 void SetupTestCACert() {
80 scoped_refptr
<net::X509Certificate
> cert_wo_nickname
=
81 net::CreateCertificateListFromFile(net::GetTestCertsDirectory(),
83 net::X509Certificate::FORMAT_AUTO
)
85 net::X509Certificate::GetPEMEncoded(cert_wo_nickname
->os_cert_handle(),
87 std::string der_encoded
;
88 net::X509Certificate::GetDEREncoded(cert_wo_nickname
->os_cert_handle(),
90 cert_wo_nickname
= NULL
;
92 test_ca_cert_
= net::X509Certificate::CreateFromBytesWithNickname(
93 der_encoded
.data(), der_encoded
.size(), kNSSNickname
);
94 net::NSSCertDatabase
* cert_database
= net::NSSCertDatabase::GetInstance();
95 net::CertificateList cert_list
;
96 cert_list
.push_back(test_ca_cert_
);
97 net::NSSCertDatabase::ImportCertFailureList failures
;
98 EXPECT_TRUE(cert_database
->ImportCACerts(
99 cert_list
, net::NSSCertDatabase::TRUST_DEFAULT
, &failures
));
100 ASSERT_TRUE(failures
.empty()) << net::ErrorToString(failures
[0].net_error
);
103 void SetupNetworkHandlers() {
104 network_state_handler_
.reset(NetworkStateHandler::InitializeForTest());
105 network_cert_migrator_
.reset(new NetworkCertMigrator
);
106 network_cert_migrator_
->Init(network_state_handler_
.get());
109 void SetupWifiWithNss() {
110 const bool add_to_visible
= true;
111 const bool add_to_watchlist
= true;
112 service_test_
->AddService(kWifiStub
,
118 service_test_
->SetServiceProperty(kWifiStub
,
119 shill::kEapCaCertNssProperty
,
120 base::StringValue(kNSSNickname
));
123 void GetEapCACertProperties(std::string
* nss_nickname
, std::string
* ca_pem
) {
124 nss_nickname
->clear();
126 const base::DictionaryValue
* properties
=
127 service_test_
->GetServiceProperties(kWifiStub
);
128 properties
->GetStringWithoutPathExpansion(shill::kEapCaCertNssProperty
,
130 const base::ListValue
* ca_pems
= NULL
;
131 properties
->GetListWithoutPathExpansion(shill::kEapCaCertPemProperty
,
133 if (ca_pems
&& !ca_pems
->empty())
134 ca_pems
->GetString(0, ca_pem
);
137 void SetupVpnWithNss(bool open_vpn
) {
138 const bool add_to_visible
= true;
139 const bool add_to_watchlist
= true;
140 service_test_
->AddService(kVPNStub
,
146 base::DictionaryValue provider
;
147 const char* nss_property
= open_vpn
? shill::kOpenVPNCaCertNSSProperty
148 : shill::kL2tpIpsecCaCertNssProperty
;
149 provider
.SetStringWithoutPathExpansion(nss_property
, kNSSNickname
);
150 service_test_
->SetServiceProperty(
151 kVPNStub
, shill::kProviderProperty
, provider
);
154 void GetVpnCACertProperties(bool open_vpn
,
155 std::string
* nss_nickname
,
156 std::string
* ca_pem
) {
157 nss_nickname
->clear();
159 const base::DictionaryValue
* properties
=
160 service_test_
->GetServiceProperties(kVPNStub
);
161 const base::DictionaryValue
* provider
= NULL
;
162 properties
->GetDictionaryWithoutPathExpansion(shill::kProviderProperty
,
166 const char* nss_property
= open_vpn
? shill::kOpenVPNCaCertNSSProperty
167 : shill::kL2tpIpsecCaCertNssProperty
;
168 provider
->GetStringWithoutPathExpansion(nss_property
, nss_nickname
);
169 const base::ListValue
* ca_pems
= NULL
;
170 const char* pem_property
= open_vpn
? shill::kOpenVPNCaCertPemProperty
171 : shill::kL2tpIpsecCaCertPemProperty
;
172 provider
->GetListWithoutPathExpansion(pem_property
, &ca_pems
);
173 if (ca_pems
&& !ca_pems
->empty())
174 ca_pems
->GetString(0, ca_pem
);
177 ShillServiceClient::TestInterface
* service_test_
;
178 scoped_refptr
<net::X509Certificate
> test_ca_cert_
;
179 std::string test_ca_cert_pem_
;
180 base::MessageLoop message_loop_
;
183 void CleanupTestCert() {
184 ASSERT_TRUE(net::NSSCertDatabase::GetInstance()->DeleteCertAndKey(
185 test_ca_cert_
.get()));
188 scoped_ptr
<NetworkStateHandler
> network_state_handler_
;
189 scoped_ptr
<NetworkCertMigrator
> network_cert_migrator_
;
190 scoped_refptr
<net::CryptoModule
> slot_
;
191 crypto::ScopedTestNSSDB test_nssdb_
;
193 DISALLOW_COPY_AND_ASSIGN(NetworkCertMigratorTest
);
196 TEST_F(NetworkCertMigratorTest
, MigrateNssOnInitialization
) {
197 // Add a new network for migration before the handlers are initialized.
200 SetupNetworkHandlers();
202 message_loop_
.RunUntilIdle();
203 std::string nss_nickname
, ca_pem
;
204 GetEapCACertProperties(&nss_nickname
, &ca_pem
);
205 EXPECT_TRUE(nss_nickname
.empty());
206 EXPECT_EQ(test_ca_cert_pem_
, ca_pem
);
209 TEST_F(NetworkCertMigratorTest
, MigrateNssOnNetworkAppearance
) {
211 SetupNetworkHandlers();
212 message_loop_
.RunUntilIdle();
214 // Add a new network for migration after the handlers are initialized.
217 message_loop_
.RunUntilIdle();
218 std::string nss_nickname
, ca_pem
;
219 GetEapCACertProperties(&nss_nickname
, &ca_pem
);
220 EXPECT_TRUE(nss_nickname
.empty());
221 EXPECT_EQ(test_ca_cert_pem_
, ca_pem
);
224 TEST_F(NetworkCertMigratorTest
, DoNotMigrateNssIfPemSet
) {
225 // Add a new network with an already set PEM property.
227 base::ListValue ca_pems
;
228 ca_pems
.AppendString(kFakePEM
);
229 service_test_
->SetServiceProperty(
230 kWifiStub
, shill::kEapCaCertPemProperty
, ca_pems
);
233 SetupNetworkHandlers();
234 message_loop_
.RunUntilIdle();
236 std::string nss_nickname
, ca_pem
;
237 GetEapCACertProperties(&nss_nickname
, &ca_pem
);
238 EXPECT_TRUE(nss_nickname
.empty());
239 EXPECT_EQ(kFakePEM
, ca_pem
);
242 TEST_F(NetworkCertMigratorTest
, MigrateOpenVpn
) {
243 // Add a new network for migration before the handlers are initialized.
244 SetupVpnWithNss(true /* OpenVPN */);
247 SetupNetworkHandlers();
249 message_loop_
.RunUntilIdle();
250 std::string nss_nickname
, ca_pem
;
251 GetVpnCACertProperties(true /* OpenVPN */, &nss_nickname
, &ca_pem
);
252 EXPECT_TRUE(nss_nickname
.empty());
253 EXPECT_EQ(test_ca_cert_pem_
, ca_pem
);
256 TEST_F(NetworkCertMigratorTest
, MigrateIpsecVpn
) {
257 // Add a new network for migration before the handlers are initialized.
258 SetupVpnWithNss(false /* not OpenVPN */);
261 SetupNetworkHandlers();
263 message_loop_
.RunUntilIdle();
264 std::string nss_nickname
, ca_pem
;
265 GetVpnCACertProperties(false /* not OpenVPN */, &nss_nickname
, &ca_pem
);
266 EXPECT_TRUE(nss_nickname
.empty());
267 EXPECT_EQ(test_ca_cert_pem_
, ca_pem
);
271 } // namespace chromeos