OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 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 |
| 26 namespace chromeos { |
| 27 |
| 28 namespace { |
| 29 |
| 30 const char* kWifiStub = "wifi_stub"; |
| 31 const char* kVPNStub = "vpn_stub"; |
| 32 const char* kNSSNickname = "nss_nickname"; |
| 33 const char* kFakePEM = "pem"; |
| 34 |
| 35 } // namespace |
| 36 |
| 37 class 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 |
| 189 TEST_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 |
| 202 TEST_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 |
| 217 TEST_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 |
| 235 TEST_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 |
| 249 TEST_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 |
OLD | NEW |