network_configuration_updater_unittest.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
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 6#include "base/callback.h" 7#include "base/files/file_path.h" 8#include "base/memory/scoped_ptr.h" 9#include "base/run_loop.h" 10#include "base/values.h" 11#include "chrome/browser/chromeos/login/user.h" 12#include "chrome/browser/chromeos/policy/policy_cert_verifier.h" 13#include "chrome/browser/chromeos/policy/user_network_configuration_updater.h" 14#include "chrome/browser/policy/external_data_fetcher.h" 15#include "chrome/browser/policy/mock_configuration_policy_provider.h" 16#include "chrome/browser/policy/policy_map.h" 17#include "chrome/browser/policy/policy_service_impl.h" 18#include "chromeos/network/mock_managed_network_configuration_handler.h" 19#include "chromeos/network/onc/mock_certificate_importer.h" 20#include "chromeos/network/onc/onc_test_utils.h" 21#include "chromeos/network/onc/onc_utils.h" 22#include "components/onc/onc_constants.h" 23#include "content/public/test/test_browser_thread_bundle.h" 24#include "content/public/test/test_utils.h" 25#include "net/base/test_data_directory.h" 26#include "net/cert/x509_certificate.h" 27#include "net/test/cert_test_util.h" 28#include "policy/policy_constants.h" 29#include "testing/gmock/include/gmock/gmock.h" 30#include "testing/gtest/include/gtest/gtest.h" 31 32using testing::AnyNumber; 33using testing::AtLeast; 34using testing::Mock; 35using testing::Ne; 36using testing::Return; 37using testing::StrictMock; 38using testing::_; 39 40namespace policy { 41 42namespace { 43 44const char kFakeUserEmail[] = "fake email"; 45const char kFakeUsernameHash[] = "fake hash"; 46 47class FakeUser : public chromeos::User { 48 public: 49 FakeUser() : User(kFakeUserEmail) { 50 set_display_email(kFakeUserEmail); 51 set_username_hash(kFakeUsernameHash); 52 } 53 virtual ~FakeUser() {} 54 55 // User overrides 56 virtual UserType GetType() const OVERRIDE { 57 return USER_TYPE_REGULAR; 58 } 59 60 private: 61 DISALLOW_COPY_AND_ASSIGN(FakeUser); 62}; 63 64const char kFakeONC[] = 65 "{ \"NetworkConfigurations\": [" 66 " { \"GUID\": \"{485d6076-dd44-6b6d-69787465725f5040}\"," 67 " \"Type\": \"WiFi\"," 68 " \"Name\": \"My WiFi Network\"," 69 " \"WiFi\": {" 70 " \"SSID\": \"ssid-none\"," 71 " \"Security\": \"None\" }" 72 " }" 73 " ]," 74 " \"GlobalNetworkConfiguration\": {" 75 " \"AllowOnlyPolicyNetworksToAutoconnect\": true," 76 " }," 77 " \"Certificates\": [" 78 " { \"GUID\": \"{f998f760-272b-6939-4c2beffe428697ac}\"," 79 " \"PKCS12\": \"abc\"," 80 " \"Type\": \"Client\" }" 81 " ]," 82 " \"Type\": \"UnencryptedConfiguration\"" 83 "}"; 84 85std::string ValueToString(const base::Value& value) { 86 std::stringstream str; 87 str << value; 88 return str.str(); 89} 90 91void AppendAll(const base::ListValue& from, base::ListValue* to) { 92 for (base::ListValue::const_iterator it = from.begin(); it != from.end(); 93 ++it) { 94 to->Append((*it)->DeepCopy()); 95 } 96} 97 98// Matcher to match base::Value. 99MATCHER_P(IsEqualTo, 100 value, 101 std::string(negation ? "isn't" : "is") + " equal to " + 102 ValueToString(*value)) { 103 return value->Equals(&arg); 104} 105 106MATCHER(IsEmpty, std::string(negation ? "isn't" : "is") + " empty.") { 107 return arg.empty(); 108} 109 110ACTION_P(SetCertificateList, list) { 111 if (arg2) 112 *arg2 = list; 113 return true; 114} 115 116} // namespace 117 118class NetworkConfigurationUpdaterTest : public testing::Test { 119 protected: 120 NetworkConfigurationUpdaterTest() { 121 } 122 123 virtual void SetUp() OVERRIDE { 124 EXPECT_CALL(provider_, IsInitializationComplete(_)) 125 .WillRepeatedly(Return(true)); 126 provider_.Init(); 127 PolicyServiceImpl::Providers providers; 128 providers.push_back(&provider_); 129 policy_service_.reset(new PolicyServiceImpl(providers)); 130 131 scoped_ptr<base::DictionaryValue> fake_toplevel_onc = 132 chromeos::onc::ReadDictionaryFromJson(kFakeONC); 133 134 base::ListValue* network_configs = NULL; 135 fake_toplevel_onc->GetListWithoutPathExpansion( 136 onc::toplevel_config::kNetworkConfigurations, &network_configs); 137 AppendAll(*network_configs, &fake_network_configs_); 138 139 base::DictionaryValue* global_config = NULL; 140 fake_toplevel_onc->GetDictionaryWithoutPathExpansion( 141 onc::toplevel_config::kGlobalNetworkConfiguration, &global_config); 142 fake_global_network_config_.MergeDictionary(global_config); 143 144 base::ListValue* certs = NULL; 145 fake_toplevel_onc->GetListWithoutPathExpansion( 146 onc::toplevel_config::kCertificates, &certs); 147 AppendAll(*certs, &fake_certificates_); 148 149 certificate_importer_ = 150 new StrictMock<chromeos::onc::MockCertificateImporter>(); 151 certificate_importer_owned_.reset(certificate_importer_); 152 } 153 154 virtual void TearDown() OVERRIDE { 155 network_configuration_updater_.reset(); 156 provider_.Shutdown(); 157 base::RunLoop().RunUntilIdle(); 158 } 159 160 void UpdateProviderPolicy(const PolicyMap& policy) { 161 provider_.UpdateChromePolicy(policy); 162 base::RunLoop().RunUntilIdle(); 163 } 164 165 UserNetworkConfigurationUpdater* 166 CreateNetworkConfigurationUpdaterForUserPolicy( 167 bool allow_trusted_certs_from_policy) { 168 UserNetworkConfigurationUpdater* updater = 169 UserNetworkConfigurationUpdater::CreateForUserPolicy( 170 allow_trusted_certs_from_policy, 171 fake_user_, 172 certificate_importer_owned_.Pass(), 173 policy_service_.get(), 174 &network_config_handler_).release(); 175 network_configuration_updater_.reset(updater); 176 return updater; 177 } 178 179 void CreateNetworkConfigurationUpdaterForDevicePolicy() { 180 network_configuration_updater_ = 181 NetworkConfigurationUpdater::CreateForDevicePolicy( 182 certificate_importer_owned_.Pass(), 183 policy_service_.get(), 184 &network_config_handler_); 185 } 186 187 base::ListValue fake_network_configs_; 188 base::DictionaryValue fake_global_network_config_; 189 base::ListValue fake_certificates_; 190 StrictMock<chromeos::MockManagedNetworkConfigurationHandler> 191 network_config_handler_; 192 193 // Ownership of certificate_importer_owned_ is passed to the 194 // NetworkConfigurationUpdater. When that happens, |certificate_importer_| 195 // continues to point to that instance but |certificate_importer_owned_| is 196 // released. 197 StrictMock<chromeos::onc::MockCertificateImporter>* certificate_importer_; 198 scoped_ptr<chromeos::onc::CertificateImporter> certificate_importer_owned_; 199 200 StrictMock<MockConfigurationPolicyProvider> provider_; 201 scoped_ptr<PolicyServiceImpl> policy_service_; 202 FakeUser fake_user_; 203 204 scoped_ptr<NetworkConfigurationUpdater> network_configuration_updater_; 205 content::TestBrowserThreadBundle thread_bundle_; 206}; 207 208TEST_F(NetworkConfigurationUpdaterTest, PolicyIsValidatedAndRepaired) { 209 std::string onc_policy = 210 chromeos::onc::test_utils::ReadTestData("toplevel_partially_invalid.onc"); 211 212 scoped_ptr<base::DictionaryValue> onc_repaired = 213 chromeos::onc::test_utils::ReadTestDictionary( 214 "repaired_toplevel_partially_invalid.onc"); 215 216 base::ListValue* network_configs_repaired = NULL; 217 onc_repaired->GetListWithoutPathExpansion( 218 onc::toplevel_config::kNetworkConfigurations, &network_configs_repaired); 219 ASSERT_TRUE(network_configs_repaired); 220 221 base::DictionaryValue* global_config_repaired = NULL; 222 onc_repaired->GetDictionaryWithoutPathExpansion( 223 onc::toplevel_config::kGlobalNetworkConfiguration, 224 &global_config_repaired); 225 ASSERT_TRUE(global_config_repaired); 226 227 PolicyMap policy; 228 policy.Set(key::kOpenNetworkConfiguration, 229 POLICY_LEVEL_MANDATORY, 230 POLICY_SCOPE_USER, 231 new base::StringValue(onc_policy), 232 NULL); 233 UpdateProviderPolicy(policy); 234 235 EXPECT_CALL(network_config_handler_, 236 SetPolicy(onc::ONC_SOURCE_USER_POLICY, 237 _, 238 IsEqualTo(network_configs_repaired), 239 IsEqualTo(global_config_repaired))); 240 EXPECT_CALL(*certificate_importer_, 241 ImportCertificates(_, onc::ONC_SOURCE_USER_POLICY, _)); 242 243 CreateNetworkConfigurationUpdaterForUserPolicy( 244 false /* do not allow trusted certs from policy */ ); 245} 246 247TEST_F(NetworkConfigurationUpdaterTest, 248 DoNotAllowTrustedCertificatesFromPolicy) { 249 net::CertificateList cert_list; 250 cert_list = 251 net::CreateCertificateListFromFile(net::GetTestCertsDirectory(), 252 "ok_cert.pem", 253 net::X509Certificate::FORMAT_AUTO); 254 ASSERT_EQ(1u, cert_list.size()); 255 256 EXPECT_CALL(network_config_handler_, 257 SetPolicy(onc::ONC_SOURCE_USER_POLICY, _, _, _)); 258 EXPECT_CALL(*certificate_importer_, ImportCertificates(_, _, _)) 259 .WillRepeatedly(SetCertificateList(cert_list)); 260 261 UserNetworkConfigurationUpdater* updater = 262 CreateNetworkConfigurationUpdaterForUserPolicy( 263 false /* do not allow trusted certs from policy */); 264 265 // Certificates with the "Web" trust flag set should not be forwarded to the 266 // trust provider. 267 policy::PolicyCertVerifier cert_verifier(( 268 base::Closure() /* no policy cert trusted callback */)); 269 updater->SetPolicyCertVerifier(&cert_verifier); 270 base::RunLoop().RunUntilIdle(); 271 EXPECT_TRUE(cert_verifier.GetAdditionalTrustAnchors().empty()); 272 273 // |cert_verifier| must outlive the updater. 274 network_configuration_updater_.reset(); 275} 276 277TEST_F(NetworkConfigurationUpdaterTest, AllowTrustedCertificatesFromPolicy) { 278 net::CertificateList cert_list; 279 cert_list = 280 net::CreateCertificateListFromFile(net::GetTestCertsDirectory(), 281 "ok_cert.pem", 282 net::X509Certificate::FORMAT_AUTO); 283 ASSERT_EQ(1u, cert_list.size()); 284 285 EXPECT_CALL(network_config_handler_, 286 SetPolicy(onc::ONC_SOURCE_USER_POLICY, _, _, _)); 287 EXPECT_CALL(*certificate_importer_, 288 ImportCertificates(_, onc::ONC_SOURCE_USER_POLICY, _)) 289 .WillRepeatedly(SetCertificateList(cert_list)); 290 291 UserNetworkConfigurationUpdater* updater = 292 CreateNetworkConfigurationUpdaterForUserPolicy( 293 true /* allow trusted certs from policy */); 294 295 // Certificates with the "Web" trust flag set should be forwarded to the 296 // trust provider. 297 policy::PolicyCertVerifier cert_verifier(( 298 base::Closure() /* no policy cert trusted callback */)); 299 updater->SetPolicyCertVerifier(&cert_verifier); 300 base::RunLoop().RunUntilIdle(); 301 EXPECT_EQ(1u, cert_verifier.GetAdditionalTrustAnchors().size()); 302 303 // |cert_verifier| must outlive the updater. 304 network_configuration_updater_.reset(); 305} 306 307class NetworkConfigurationUpdaterTestWithParam 308 : public NetworkConfigurationUpdaterTest, 309 public testing::WithParamInterface<const char*> { 310 protected: 311 // Returns the currently tested ONC source. 312 onc::ONCSource CurrentONCSource() { 313 if (GetParam() == key::kOpenNetworkConfiguration) 314 return onc::ONC_SOURCE_USER_POLICY; 315 DCHECK(GetParam() == key::kDeviceOpenNetworkConfiguration); 316 return onc::ONC_SOURCE_DEVICE_POLICY; 317 } 318 319 // Returns the expected username hash to push policies to 320 // ManagedNetworkConfigurationHandler. 321 std::string ExpectedUsernameHash() { 322 if (GetParam() == key::kOpenNetworkConfiguration) 323 return kFakeUsernameHash; 324 return std::string(); 325 } 326 327 void CreateNetworkConfigurationUpdater() { 328 if (GetParam() == key::kOpenNetworkConfiguration) { 329 CreateNetworkConfigurationUpdaterForUserPolicy( 330 false /* do not allow trusted certs from policy */); 331 } else { 332 CreateNetworkConfigurationUpdaterForDevicePolicy(); 333 } 334 } 335}; 336 337TEST_P(NetworkConfigurationUpdaterTestWithParam, InitialUpdates) { 338 PolicyMap policy; 339 policy.Set(GetParam(), POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, 340 new base::StringValue(kFakeONC), NULL); 341 UpdateProviderPolicy(policy); 342 343 EXPECT_CALL(network_config_handler_, 344 SetPolicy(CurrentONCSource(), 345 ExpectedUsernameHash(), 346 IsEqualTo(&fake_network_configs_), 347 IsEqualTo(&fake_global_network_config_))); 348 EXPECT_CALL(*certificate_importer_, 349 ImportCertificates( 350 IsEqualTo(&fake_certificates_), CurrentONCSource(), _)); 351 352 CreateNetworkConfigurationUpdater(); 353} 354 355 356TEST_P(NetworkConfigurationUpdaterTestWithParam, PolicyChange) { 357 // Ignore the initial updates. 358 EXPECT_CALL(network_config_handler_, SetPolicy(_, _, _, _)).Times(AtLeast(1)); 359 EXPECT_CALL(*certificate_importer_, ImportCertificates(_, _, _)) 360 .Times(AtLeast(1)); 361 CreateNetworkConfigurationUpdater(); 362 Mock::VerifyAndClearExpectations(&network_config_handler_); 363 Mock::VerifyAndClearExpectations(certificate_importer_); 364 365 // The Updater should update if policy changes. 366 EXPECT_CALL(network_config_handler_, 367 SetPolicy(CurrentONCSource(), 368 _, 369 IsEqualTo(&fake_network_configs_), 370 IsEqualTo(&fake_global_network_config_))); 371 EXPECT_CALL(*certificate_importer_, 372 ImportCertificates( 373 IsEqualTo(&fake_certificates_), CurrentONCSource(), _)); 374 375 PolicyMap policy; 376 policy.Set(GetParam(), POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, 377 new base::StringValue(kFakeONC), NULL); 378 UpdateProviderPolicy(policy); 379 Mock::VerifyAndClearExpectations(&network_config_handler_); 380 Mock::VerifyAndClearExpectations(certificate_importer_); 381 382 // Another update is expected if the policy goes away. 383 EXPECT_CALL(network_config_handler_, 384 SetPolicy(CurrentONCSource(), _, IsEmpty(), IsEmpty())); 385 EXPECT_CALL(*certificate_importer_, 386 ImportCertificates(IsEmpty(), CurrentONCSource(), _)); 387 388 policy.Erase(GetParam()); 389 UpdateProviderPolicy(policy); 390} 391 392INSTANTIATE_TEST_CASE_P(NetworkConfigurationUpdaterTestWithParamInstance, 393 NetworkConfigurationUpdaterTestWithParam, 394 testing::Values(key::kDeviceOpenNetworkConfiguration, 395 key::kOpenNetworkConfiguration)); 396 397} // namespace policy 398