network_cert_migrator_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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/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/network/network_state_handler.h" 16#include "chromeos/tpm_token_loader.h" 17#include "crypto/nss_util.h" 18#include "crypto/nss_util_internal.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_chromeos.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" 27 28namespace chromeos { 29 30namespace { 31 32const char* kWifiStub = "wifi_stub"; 33const char* kVPNStub = "vpn_stub"; 34const char* kNSSNickname = "nss_nickname"; 35const char* kFakePEM = "pem"; 36 37} // namespace 38 39class NetworkCertMigratorTest : public testing::Test { 40 public: 41 NetworkCertMigratorTest() : service_test_(NULL), 42 user_("user_hash") { 43 } 44 virtual ~NetworkCertMigratorTest() {} 45 46 virtual void SetUp() OVERRIDE { 47 // Initialize NSS db for the user. 48 ASSERT_TRUE(user_.constructed_successfully()); 49 user_.FinishInit(); 50 test_nssdb_.reset(new net::NSSCertDatabaseChromeOS( 51 crypto::GetPublicSlotForChromeOSUser(user_.username_hash()), 52 crypto::GetPrivateSlotForChromeOSUser( 53 user_.username_hash(), 54 base::Callback<void(crypto::ScopedPK11Slot)>()))); 55 test_nssdb_->SetSlowTaskRunnerForTest(message_loop_.message_loop_proxy()); 56 57 DBusThreadManager::InitializeWithStub(); 58 service_test_ = 59 DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface(); 60 base::RunLoop().RunUntilIdle(); 61 service_test_->ClearServices(); 62 base::RunLoop().RunUntilIdle(); 63 64 CertLoader::Initialize(); 65 CertLoader* cert_loader_ = CertLoader::Get(); 66 cert_loader_->StartWithNSSDB(test_nssdb_.get()); 67 } 68 69 virtual void TearDown() OVERRIDE { 70 network_cert_migrator_.reset(); 71 network_state_handler_.reset(); 72 CertLoader::Shutdown(); 73 DBusThreadManager::Shutdown(); 74 CleanupTestCert(); 75 } 76 77 protected: 78 void SetupTestCACert() { 79 scoped_refptr<net::X509Certificate> cert_wo_nickname = 80 net::CreateCertificateListFromFile(net::GetTestCertsDirectory(), 81 "eku-test-root.pem", 82 net::X509Certificate::FORMAT_AUTO) 83 .back(); 84 net::X509Certificate::GetPEMEncoded(cert_wo_nickname->os_cert_handle(), 85 &test_ca_cert_pem_); 86 std::string der_encoded; 87 net::X509Certificate::GetDEREncoded(cert_wo_nickname->os_cert_handle(), 88 &der_encoded); 89 cert_wo_nickname = NULL; 90 91 test_ca_cert_ = net::X509Certificate::CreateFromBytesWithNickname( 92 der_encoded.data(), der_encoded.size(), kNSSNickname); 93 net::CertificateList cert_list; 94 cert_list.push_back(test_ca_cert_); 95 net::NSSCertDatabase::ImportCertFailureList failures; 96 EXPECT_TRUE(test_nssdb_->ImportCACerts( 97 cert_list, net::NSSCertDatabase::TRUST_DEFAULT, &failures)); 98 ASSERT_TRUE(failures.empty()) << net::ErrorToString(failures[0].net_error); 99 } 100 101 void SetupNetworkHandlers() { 102 network_state_handler_.reset(NetworkStateHandler::InitializeForTest()); 103 network_cert_migrator_.reset(new NetworkCertMigrator); 104 network_cert_migrator_->Init(network_state_handler_.get()); 105 } 106 107 void SetupWifiWithNss() { 108 const bool add_to_visible = true; 109 const bool add_to_watchlist = true; 110 service_test_->AddService(kWifiStub, 111 kWifiStub, 112 shill::kTypeWifi, 113 shill::kStateOnline, 114 add_to_visible, 115 add_to_watchlist); 116 service_test_->SetServiceProperty(kWifiStub, 117 shill::kEapCaCertNssProperty, 118 base::StringValue(kNSSNickname)); 119 } 120 121 void GetEapCACertProperties(std::string* nss_nickname, std::string* ca_pem) { 122 nss_nickname->clear(); 123 ca_pem->clear(); 124 const base::DictionaryValue* properties = 125 service_test_->GetServiceProperties(kWifiStub); 126 properties->GetStringWithoutPathExpansion(shill::kEapCaCertNssProperty, 127 nss_nickname); 128 const base::ListValue* ca_pems = NULL; 129 properties->GetListWithoutPathExpansion(shill::kEapCaCertPemProperty, 130 &ca_pems); 131 if (ca_pems && !ca_pems->empty()) 132 ca_pems->GetString(0, ca_pem); 133 } 134 135 void SetupVpnWithNss(bool open_vpn) { 136 const bool add_to_visible = true; 137 const bool add_to_watchlist = true; 138 service_test_->AddService(kVPNStub, 139 kVPNStub, 140 shill::kTypeVPN, 141 shill::kStateIdle, 142 add_to_visible, 143 add_to_watchlist); 144 base::DictionaryValue provider; 145 const char* nss_property = open_vpn ? shill::kOpenVPNCaCertNSSProperty 146 : shill::kL2tpIpsecCaCertNssProperty; 147 provider.SetStringWithoutPathExpansion(nss_property, kNSSNickname); 148 service_test_->SetServiceProperty( 149 kVPNStub, shill::kProviderProperty, provider); 150 } 151 152 void GetVpnCACertProperties(bool open_vpn, 153 std::string* nss_nickname, 154 std::string* ca_pem) { 155 nss_nickname->clear(); 156 ca_pem->clear(); 157 const base::DictionaryValue* properties = 158 service_test_->GetServiceProperties(kVPNStub); 159 const base::DictionaryValue* provider = NULL; 160 properties->GetDictionaryWithoutPathExpansion(shill::kProviderProperty, 161 &provider); 162 if (!provider) 163 return; 164 const char* nss_property = open_vpn ? shill::kOpenVPNCaCertNSSProperty 165 : shill::kL2tpIpsecCaCertNssProperty; 166 provider->GetStringWithoutPathExpansion(nss_property, nss_nickname); 167 const base::ListValue* ca_pems = NULL; 168 const char* pem_property = open_vpn ? shill::kOpenVPNCaCertPemProperty 169 : shill::kL2tpIpsecCaCertPemProperty; 170 provider->GetListWithoutPathExpansion(pem_property, &ca_pems); 171 if (ca_pems && !ca_pems->empty()) 172 ca_pems->GetString(0, ca_pem); 173 } 174 175 ShillServiceClient::TestInterface* service_test_; 176 scoped_refptr<net::X509Certificate> test_ca_cert_; 177 std::string test_ca_cert_pem_; 178 base::MessageLoop message_loop_; 179 180 private: 181 void CleanupTestCert() { 182 ASSERT_TRUE(test_nssdb_->DeleteCertAndKey(test_ca_cert_.get())); 183 } 184 185 scoped_ptr<NetworkStateHandler> network_state_handler_; 186 scoped_ptr<NetworkCertMigrator> network_cert_migrator_; 187 crypto::ScopedTestNSSChromeOSUser user_; 188 scoped_ptr<net::NSSCertDatabaseChromeOS> test_nssdb_; 189 190 DISALLOW_COPY_AND_ASSIGN(NetworkCertMigratorTest); 191}; 192 193TEST_F(NetworkCertMigratorTest, MigrateNssOnInitialization) { 194 // Add a new network for migration before the handlers are initialized. 195 SetupWifiWithNss(); 196 SetupTestCACert(); 197 SetupNetworkHandlers(); 198 199 base::RunLoop().RunUntilIdle(); 200 std::string nss_nickname, ca_pem; 201 GetEapCACertProperties(&nss_nickname, &ca_pem); 202 EXPECT_TRUE(nss_nickname.empty()); 203 EXPECT_EQ(test_ca_cert_pem_, ca_pem); 204} 205 206TEST_F(NetworkCertMigratorTest, MigrateNssOnNetworkAppearance) { 207 SetupTestCACert(); 208 SetupNetworkHandlers(); 209 base::RunLoop().RunUntilIdle(); 210 211 // Add a new network for migration after the handlers are initialized. 212 SetupWifiWithNss(); 213 214 base::RunLoop().RunUntilIdle(); 215 std::string nss_nickname, ca_pem; 216 GetEapCACertProperties(&nss_nickname, &ca_pem); 217 EXPECT_TRUE(nss_nickname.empty()); 218 EXPECT_EQ(test_ca_cert_pem_, ca_pem); 219} 220 221TEST_F(NetworkCertMigratorTest, DoNotMigrateNssIfPemSet) { 222 // Add a new network with an already set PEM property. 223 SetupWifiWithNss(); 224 base::ListValue ca_pems; 225 ca_pems.AppendString(kFakePEM); 226 service_test_->SetServiceProperty( 227 kWifiStub, shill::kEapCaCertPemProperty, ca_pems); 228 229 SetupTestCACert(); 230 SetupNetworkHandlers(); 231 base::RunLoop().RunUntilIdle(); 232 233 std::string nss_nickname, ca_pem; 234 GetEapCACertProperties(&nss_nickname, &ca_pem); 235 EXPECT_TRUE(nss_nickname.empty()); 236 EXPECT_EQ(kFakePEM, ca_pem); 237} 238 239TEST_F(NetworkCertMigratorTest, MigrateOpenVpn) { 240 // Add a new network for migration before the handlers are initialized. 241 SetupVpnWithNss(true /* OpenVPN */); 242 243 SetupTestCACert(); 244 SetupNetworkHandlers(); 245 246 base::RunLoop().RunUntilIdle(); 247 std::string nss_nickname, ca_pem; 248 GetVpnCACertProperties(true /* OpenVPN */, &nss_nickname, &ca_pem); 249 EXPECT_TRUE(nss_nickname.empty()); 250 EXPECT_EQ(test_ca_cert_pem_, ca_pem); 251} 252 253TEST_F(NetworkCertMigratorTest, MigrateIpsecVpn) { 254 // Add a new network for migration before the handlers are initialized. 255 SetupVpnWithNss(false /* not OpenVPN */); 256 257 SetupTestCACert(); 258 SetupNetworkHandlers(); 259 260 base::RunLoop().RunUntilIdle(); 261 std::string nss_nickname, ca_pem; 262 GetVpnCACertProperties(false /* not OpenVPN */, &nss_nickname, &ca_pem); 263 EXPECT_TRUE(nss_nickname.empty()); 264 EXPECT_EQ(test_ca_cert_pem_, ca_pem); 265} 266 267} // namespace chromeos 268