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