OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromeos/network/network_cert_migrator.h" | 5 #include "chromeos/network/network_cert_migrator.h" |
6 | 6 |
7 #include <cert.h> | 7 #include <cert.h> |
8 | 8 |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
11 #include "base/run_loop.h" | 11 #include "base/run_loop.h" |
| 12 #include "base/strings/string_number_conversions.h" |
12 #include "chromeos/cert_loader.h" | 13 #include "chromeos/cert_loader.h" |
13 #include "chromeos/dbus/dbus_thread_manager.h" | 14 #include "chromeos/dbus/dbus_thread_manager.h" |
14 #include "chromeos/dbus/shill_service_client.h" | 15 #include "chromeos/dbus/shill_service_client.h" |
15 #include "chromeos/network/network_state_handler.h" | 16 #include "chromeos/network/network_state_handler.h" |
16 #include "chromeos/tpm_token_loader.h" | 17 #include "chromeos/tpm_token_loader.h" |
17 #include "crypto/nss_util_internal.h" | 18 #include "crypto/nss_util_internal.h" |
18 #include "crypto/scoped_test_nss_chromeos_user.h" | 19 #include "crypto/scoped_test_nss_chromeos_user.h" |
19 #include "net/base/crypto_module.h" | 20 #include "net/base/crypto_module.h" |
20 #include "net/base/net_errors.h" | 21 #include "net/base/net_errors.h" |
21 #include "net/base/test_data_directory.h" | 22 #include "net/base/test_data_directory.h" |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 test_ca_cert_ = net::X509Certificate::CreateFromBytesWithNickname( | 92 test_ca_cert_ = net::X509Certificate::CreateFromBytesWithNickname( |
92 der_encoded.data(), der_encoded.size(), kNSSNickname); | 93 der_encoded.data(), der_encoded.size(), kNSSNickname); |
93 net::CertificateList cert_list; | 94 net::CertificateList cert_list; |
94 cert_list.push_back(test_ca_cert_); | 95 cert_list.push_back(test_ca_cert_); |
95 net::NSSCertDatabase::ImportCertFailureList failures; | 96 net::NSSCertDatabase::ImportCertFailureList failures; |
96 EXPECT_TRUE(test_nssdb_->ImportCACerts( | 97 EXPECT_TRUE(test_nssdb_->ImportCACerts( |
97 cert_list, net::NSSCertDatabase::TRUST_DEFAULT, &failures)); | 98 cert_list, net::NSSCertDatabase::TRUST_DEFAULT, &failures)); |
98 ASSERT_TRUE(failures.empty()) << net::ErrorToString(failures[0].net_error); | 99 ASSERT_TRUE(failures.empty()) << net::ErrorToString(failures[0].net_error); |
99 } | 100 } |
100 | 101 |
| 102 void SetupTestClientCert() { |
| 103 std::string pkcs12_data; |
| 104 ASSERT_TRUE(base::ReadFileToString( |
| 105 net::GetTestCertsDirectory().Append("websocket_client_cert.p12"), |
| 106 &pkcs12_data)); |
| 107 |
| 108 net::CertificateList client_cert_list; |
| 109 scoped_refptr<net::CryptoModule> module(net::CryptoModule::CreateFromHandle( |
| 110 test_nssdb_->GetPrivateSlot().get())); |
| 111 ASSERT_EQ( |
| 112 net::OK, |
| 113 test_nssdb_->ImportFromPKCS12( |
| 114 module, pkcs12_data, base::string16(), false, &client_cert_list)); |
| 115 ASSERT_TRUE(!client_cert_list.empty()); |
| 116 test_client_cert_ = client_cert_list[0]; |
| 117 |
| 118 int slot_id = -1; |
| 119 test_client_cert_pkcs11_id_ = CertLoader::GetPkcs11IdAndSlotForCert( |
| 120 *test_client_cert_, &slot_id); |
| 121 ASSERT_FALSE(test_client_cert_pkcs11_id_.empty()); |
| 122 ASSERT_NE(-1, slot_id); |
| 123 test_client_cert_slot_id_ = base::IntToString(slot_id); |
| 124 } |
| 125 |
101 void SetupNetworkHandlers() { | 126 void SetupNetworkHandlers() { |
102 network_state_handler_.reset(NetworkStateHandler::InitializeForTest()); | 127 network_state_handler_.reset(NetworkStateHandler::InitializeForTest()); |
103 network_cert_migrator_.reset(new NetworkCertMigrator); | 128 network_cert_migrator_.reset(new NetworkCertMigrator); |
104 network_cert_migrator_->Init(network_state_handler_.get()); | 129 network_cert_migrator_->Init(network_state_handler_.get()); |
105 } | 130 } |
106 | 131 |
107 void AddService(const std::string& network_id, | 132 void AddService(const std::string& network_id, |
108 const std::string& type, | 133 const std::string& type, |
109 const std::string& state) { | 134 const std::string& state) { |
110 service_test_->AddService(network_id /* service_path */, | 135 service_test_->AddService(network_id /* service_path */, |
111 network_id /* guid */, | 136 network_id /* guid */, |
112 network_id /* name */, | 137 network_id /* name */, |
113 type, | 138 type, |
114 state, | 139 state, |
115 true /* add_to_visible */); | 140 true /* add_to_visible */); |
116 } | 141 } |
117 | 142 |
118 void SetupWifiWithNss() { | 143 void SetupWifiWithNss() { |
119 AddService(kWifiStub, shill::kTypeWifi, shill::kStateOnline); | 144 AddService(kWifiStub, shill::kTypeWifi, shill::kStateOnline); |
120 service_test_->SetServiceProperty(kWifiStub, | 145 service_test_->SetServiceProperty(kWifiStub, |
121 shill::kEapCaCertNssProperty, | 146 shill::kEapCaCertNssProperty, |
122 base::StringValue(kNSSNickname)); | 147 base::StringValue(kNSSNickname)); |
123 } | 148 } |
124 | 149 |
| 150 void SetupWifiWithEapCertId(const std::string& cert_id) { |
| 151 AddService(kWifiStub, shill::kTypeWifi, shill::kStateOnline); |
| 152 service_test_->SetServiceProperty(kWifiStub, |
| 153 shill::kSecurityProperty, |
| 154 base::StringValue(shill::kSecurity8021x)); |
| 155 service_test_->SetServiceProperty( |
| 156 kWifiStub, shill::kEapCertIdProperty, base::StringValue(cert_id)); |
| 157 service_test_->SetServiceProperty( |
| 158 kWifiStub, shill::kEapKeyIdProperty, base::StringValue(cert_id)); |
| 159 } |
| 160 |
| 161 void GetEapCertId(std::string* cert_id) { |
| 162 cert_id->clear(); |
| 163 const base::DictionaryValue* properties = |
| 164 service_test_->GetServiceProperties(kWifiStub); |
| 165 properties->GetStringWithoutPathExpansion(shill::kEapCertIdProperty, |
| 166 cert_id); |
| 167 } |
| 168 |
| 169 void SetupVpnWithCertId(bool open_vpn, |
| 170 const std::string& slot_id, |
| 171 const std::string& pkcs11_id) { |
| 172 AddService(kVPNStub, shill::kTypeVPN, shill::kStateIdle); |
| 173 base::DictionaryValue provider; |
| 174 if (open_vpn) { |
| 175 provider.SetStringWithoutPathExpansion(shill::kTypeProperty, |
| 176 shill::kProviderOpenVpn); |
| 177 provider.SetStringWithoutPathExpansion( |
| 178 shill::kOpenVPNClientCertIdProperty, pkcs11_id); |
| 179 } else { |
| 180 provider.SetStringWithoutPathExpansion(shill::kTypeProperty, |
| 181 shill::kProviderL2tpIpsec); |
| 182 provider.SetStringWithoutPathExpansion( |
| 183 shill::kL2tpIpsecClientCertSlotProperty, slot_id); |
| 184 provider.SetStringWithoutPathExpansion( |
| 185 shill::kL2tpIpsecClientCertIdProperty, pkcs11_id); |
| 186 } |
| 187 service_test_->SetServiceProperty( |
| 188 kVPNStub, shill::kProviderProperty, provider); |
| 189 } |
| 190 |
| 191 void GetVpnCertId(bool open_vpn, |
| 192 std::string* slot_id, |
| 193 std::string* pkcs11_id) { |
| 194 slot_id->clear(); |
| 195 pkcs11_id->clear(); |
| 196 |
| 197 const base::DictionaryValue* properties = |
| 198 service_test_->GetServiceProperties(kVPNStub); |
| 199 ASSERT_TRUE(properties); |
| 200 const base::DictionaryValue* provider = NULL; |
| 201 properties->GetDictionaryWithoutPathExpansion(shill::kProviderProperty, |
| 202 &provider); |
| 203 if (!provider) |
| 204 return; |
| 205 if (open_vpn) { |
| 206 provider->GetStringWithoutPathExpansion( |
| 207 shill::kOpenVPNClientCertIdProperty, pkcs11_id); |
| 208 } else { |
| 209 provider->GetStringWithoutPathExpansion( |
| 210 shill::kL2tpIpsecClientCertSlotProperty, slot_id); |
| 211 provider->GetStringWithoutPathExpansion( |
| 212 shill::kL2tpIpsecClientCertIdProperty, pkcs11_id); |
| 213 } |
| 214 } |
| 215 |
125 void GetEapCACertProperties(std::string* nss_nickname, std::string* ca_pem) { | 216 void GetEapCACertProperties(std::string* nss_nickname, std::string* ca_pem) { |
126 nss_nickname->clear(); | 217 nss_nickname->clear(); |
127 ca_pem->clear(); | 218 ca_pem->clear(); |
128 const base::DictionaryValue* properties = | 219 const base::DictionaryValue* properties = |
129 service_test_->GetServiceProperties(kWifiStub); | 220 service_test_->GetServiceProperties(kWifiStub); |
130 properties->GetStringWithoutPathExpansion(shill::kEapCaCertNssProperty, | 221 properties->GetStringWithoutPathExpansion(shill::kEapCaCertNssProperty, |
131 nss_nickname); | 222 nss_nickname); |
132 const base::ListValue* ca_pems = NULL; | 223 const base::ListValue* ca_pems = NULL; |
133 properties->GetListWithoutPathExpansion(shill::kEapCaCertPemProperty, | 224 properties->GetListWithoutPathExpansion(shill::kEapCaCertPemProperty, |
134 &ca_pems); | 225 &ca_pems); |
(...skipping 29 matching lines...) Expand all Loading... |
164 const base::ListValue* ca_pems = NULL; | 255 const base::ListValue* ca_pems = NULL; |
165 const char* pem_property = open_vpn ? shill::kOpenVPNCaCertPemProperty | 256 const char* pem_property = open_vpn ? shill::kOpenVPNCaCertPemProperty |
166 : shill::kL2tpIpsecCaCertPemProperty; | 257 : shill::kL2tpIpsecCaCertPemProperty; |
167 provider->GetListWithoutPathExpansion(pem_property, &ca_pems); | 258 provider->GetListWithoutPathExpansion(pem_property, &ca_pems); |
168 if (ca_pems && !ca_pems->empty()) | 259 if (ca_pems && !ca_pems->empty()) |
169 ca_pems->GetString(0, ca_pem); | 260 ca_pems->GetString(0, ca_pem); |
170 } | 261 } |
171 | 262 |
172 ShillServiceClient::TestInterface* service_test_; | 263 ShillServiceClient::TestInterface* service_test_; |
173 scoped_refptr<net::X509Certificate> test_ca_cert_; | 264 scoped_refptr<net::X509Certificate> test_ca_cert_; |
| 265 scoped_refptr<net::X509Certificate> test_client_cert_; |
| 266 std::string test_client_cert_pkcs11_id_; |
| 267 std::string test_client_cert_slot_id_; |
174 std::string test_ca_cert_pem_; | 268 std::string test_ca_cert_pem_; |
175 base::MessageLoop message_loop_; | 269 base::MessageLoop message_loop_; |
176 | 270 |
177 private: | 271 private: |
178 void CleanupTestCert() { | 272 void CleanupTestCert() { |
179 ASSERT_TRUE(test_nssdb_->DeleteCertAndKey(test_ca_cert_.get())); | 273 if (test_ca_cert_) |
| 274 ASSERT_TRUE(test_nssdb_->DeleteCertAndKey(test_ca_cert_.get())); |
| 275 |
| 276 if (test_client_cert_) |
| 277 ASSERT_TRUE(test_nssdb_->DeleteCertAndKey(test_client_cert_.get())); |
180 } | 278 } |
181 | 279 |
182 scoped_ptr<NetworkStateHandler> network_state_handler_; | 280 scoped_ptr<NetworkStateHandler> network_state_handler_; |
183 scoped_ptr<NetworkCertMigrator> network_cert_migrator_; | 281 scoped_ptr<NetworkCertMigrator> network_cert_migrator_; |
184 crypto::ScopedTestNSSChromeOSUser user_; | 282 crypto::ScopedTestNSSChromeOSUser user_; |
185 scoped_ptr<net::NSSCertDatabaseChromeOS> test_nssdb_; | 283 scoped_ptr<net::NSSCertDatabaseChromeOS> test_nssdb_; |
186 | 284 |
187 DISALLOW_COPY_AND_ASSIGN(NetworkCertMigratorTest); | 285 DISALLOW_COPY_AND_ASSIGN(NetworkCertMigratorTest); |
188 }; | 286 }; |
189 | 287 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 SetupTestCACert(); | 324 SetupTestCACert(); |
227 SetupNetworkHandlers(); | 325 SetupNetworkHandlers(); |
228 base::RunLoop().RunUntilIdle(); | 326 base::RunLoop().RunUntilIdle(); |
229 | 327 |
230 std::string nss_nickname, ca_pem; | 328 std::string nss_nickname, ca_pem; |
231 GetEapCACertProperties(&nss_nickname, &ca_pem); | 329 GetEapCACertProperties(&nss_nickname, &ca_pem); |
232 EXPECT_TRUE(nss_nickname.empty()); | 330 EXPECT_TRUE(nss_nickname.empty()); |
233 EXPECT_EQ(kFakePEM, ca_pem); | 331 EXPECT_EQ(kFakePEM, ca_pem); |
234 } | 332 } |
235 | 333 |
236 TEST_F(NetworkCertMigratorTest, MigrateOpenVpn) { | 334 TEST_F(NetworkCertMigratorTest, MigrateNssOpenVpn) { |
237 // Add a new network for migration before the handlers are initialized. | 335 // Add a new network for migration before the handlers are initialized. |
238 SetupVpnWithNss(true /* OpenVPN */); | 336 SetupVpnWithNss(true /* OpenVPN */); |
239 | 337 |
240 SetupTestCACert(); | 338 SetupTestCACert(); |
241 SetupNetworkHandlers(); | 339 SetupNetworkHandlers(); |
242 | 340 |
243 base::RunLoop().RunUntilIdle(); | 341 base::RunLoop().RunUntilIdle(); |
244 std::string nss_nickname, ca_pem; | 342 std::string nss_nickname, ca_pem; |
245 GetVpnCACertProperties(true /* OpenVPN */, &nss_nickname, &ca_pem); | 343 GetVpnCACertProperties(true /* OpenVPN */, &nss_nickname, &ca_pem); |
246 EXPECT_TRUE(nss_nickname.empty()); | 344 EXPECT_TRUE(nss_nickname.empty()); |
247 EXPECT_EQ(test_ca_cert_pem_, ca_pem); | 345 EXPECT_EQ(test_ca_cert_pem_, ca_pem); |
248 } | 346 } |
249 | 347 |
250 TEST_F(NetworkCertMigratorTest, MigrateIpsecVpn) { | 348 TEST_F(NetworkCertMigratorTest, MigrateNssIpsecVpn) { |
251 // Add a new network for migration before the handlers are initialized. | 349 // Add a new network for migration before the handlers are initialized. |
252 SetupVpnWithNss(false /* not OpenVPN */); | 350 SetupVpnWithNss(false /* not OpenVPN */); |
253 | 351 |
254 SetupTestCACert(); | 352 SetupTestCACert(); |
255 SetupNetworkHandlers(); | 353 SetupNetworkHandlers(); |
256 | 354 |
257 base::RunLoop().RunUntilIdle(); | 355 base::RunLoop().RunUntilIdle(); |
258 std::string nss_nickname, ca_pem; | 356 std::string nss_nickname, ca_pem; |
259 GetVpnCACertProperties(false /* not OpenVPN */, &nss_nickname, &ca_pem); | 357 GetVpnCACertProperties(false /* not OpenVPN */, &nss_nickname, &ca_pem); |
260 EXPECT_TRUE(nss_nickname.empty()); | 358 EXPECT_TRUE(nss_nickname.empty()); |
261 EXPECT_EQ(test_ca_cert_pem_, ca_pem); | 359 EXPECT_EQ(test_ca_cert_pem_, ca_pem); |
262 } | 360 } |
263 | 361 |
| 362 TEST_F(NetworkCertMigratorTest, MigrateEapCertIdNoMatchingCert) { |
| 363 SetupTestClientCert(); |
| 364 SetupNetworkHandlers(); |
| 365 base::RunLoop().RunUntilIdle(); |
| 366 |
| 367 // Add a new network for migration after the handlers are initialized. |
| 368 SetupWifiWithEapCertId("unknown pkcs11 id"); |
| 369 |
| 370 base::RunLoop().RunUntilIdle(); |
| 371 // Since the PKCS11 ID is unknown, the certificate configuration will be |
| 372 // cleared. |
| 373 std::string cert_id; |
| 374 GetEapCertId(&cert_id); |
| 375 EXPECT_EQ(std::string(), cert_id); |
| 376 } |
| 377 |
| 378 TEST_F(NetworkCertMigratorTest, MigrateEapCertIdNoSlotId) { |
| 379 SetupTestClientCert(); |
| 380 SetupNetworkHandlers(); |
| 381 base::RunLoop().RunUntilIdle(); |
| 382 |
| 383 // Add a new network for migration after the handlers are initialized. |
| 384 SetupWifiWithEapCertId(test_client_cert_pkcs11_id_); |
| 385 |
| 386 base::RunLoop().RunUntilIdle(); |
| 387 |
| 388 std::string cert_id; |
| 389 GetEapCertId(&cert_id); |
| 390 std::string expected_cert_id = |
| 391 test_client_cert_slot_id_ + ":" + test_client_cert_pkcs11_id_; |
| 392 EXPECT_EQ(expected_cert_id, cert_id); |
| 393 } |
| 394 |
| 395 TEST_F(NetworkCertMigratorTest, MigrateEapCertIdWrongSlotId) { |
| 396 SetupTestClientCert(); |
| 397 SetupNetworkHandlers(); |
| 398 base::RunLoop().RunUntilIdle(); |
| 399 |
| 400 // Add a new network for migration after the handlers are initialized. |
| 401 SetupWifiWithEapCertId("123:" + test_client_cert_pkcs11_id_); |
| 402 |
| 403 base::RunLoop().RunUntilIdle(); |
| 404 |
| 405 std::string cert_id; |
| 406 GetEapCertId(&cert_id); |
| 407 std::string expected_cert_id = |
| 408 test_client_cert_slot_id_ + ":" + test_client_cert_pkcs11_id_; |
| 409 EXPECT_EQ(expected_cert_id, cert_id); |
| 410 } |
| 411 |
| 412 TEST_F(NetworkCertMigratorTest, DoNotChangeEapCertIdWithCorrectSlotId) { |
| 413 SetupTestClientCert(); |
| 414 SetupNetworkHandlers(); |
| 415 base::RunLoop().RunUntilIdle(); |
| 416 |
| 417 std::string expected_cert_id = |
| 418 test_client_cert_slot_id_ + ":" + test_client_cert_pkcs11_id_; |
| 419 |
| 420 // Add a new network for migration after the handlers are initialized. |
| 421 SetupWifiWithEapCertId(expected_cert_id); |
| 422 |
| 423 base::RunLoop().RunUntilIdle(); |
| 424 |
| 425 std::string cert_id; |
| 426 GetEapCertId(&cert_id); |
| 427 EXPECT_EQ(expected_cert_id, cert_id); |
| 428 } |
| 429 |
| 430 TEST_F(NetworkCertMigratorTest, IgnoreOpenVPNCertId) { |
| 431 SetupTestClientCert(); |
| 432 SetupNetworkHandlers(); |
| 433 base::RunLoop().RunUntilIdle(); |
| 434 |
| 435 const char kPkcs11Id[] = "any slot id"; |
| 436 |
| 437 // Add a new network for migration after the handlers are initialized. |
| 438 SetupVpnWithCertId( |
| 439 true /* OpenVPN */, std::string() /* no slot id */, kPkcs11Id); |
| 440 |
| 441 base::RunLoop().RunUntilIdle(); |
| 442 |
| 443 std::string pkcs11_id; |
| 444 std::string unused_slot_id; |
| 445 GetVpnCertId(true /* OpenVPN */, &unused_slot_id, &pkcs11_id); |
| 446 EXPECT_EQ(kPkcs11Id, pkcs11_id); |
| 447 } |
| 448 |
| 449 TEST_F(NetworkCertMigratorTest, MigrateIpsecCertIdWrongSlotId) { |
| 450 SetupTestClientCert(); |
| 451 SetupNetworkHandlers(); |
| 452 base::RunLoop().RunUntilIdle(); |
| 453 |
| 454 // Add a new network for migration after the handlers are initialized. |
| 455 SetupVpnWithCertId(false /* IPsec */, "123", test_client_cert_pkcs11_id_); |
| 456 |
| 457 base::RunLoop().RunUntilIdle(); |
| 458 |
| 459 std::string pkcs11_id; |
| 460 std::string slot_id; |
| 461 GetVpnCertId(false /* IPsec */, &slot_id, &pkcs11_id); |
| 462 EXPECT_EQ(test_client_cert_pkcs11_id_, pkcs11_id); |
| 463 EXPECT_EQ(test_client_cert_slot_id_, slot_id); |
| 464 } |
| 465 |
264 } // namespace chromeos | 466 } // namespace chromeos |
OLD | NEW |