network_configuration_updater_unittest.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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 "base/bind.h" 6#include "base/bind_helpers.h" 7#include "base/callback.h" 8#include "base/files/file_path.h" 9#include "base/memory/scoped_ptr.h" 10#include "base/run_loop.h" 11#include "base/values.h" 12#include "chrome/browser/chromeos/login/user.h" 13#include "chrome/browser/chromeos/policy/user_network_configuration_updater.h" 14#include "chromeos/network/mock_managed_network_configuration_handler.h" 15#include "chromeos/network/onc/mock_certificate_importer.h" 16#include "chromeos/network/onc/onc_test_utils.h" 17#include "chromeos/network/onc/onc_utils.h" 18#include "components/onc/onc_constants.h" 19#include "components/policy/core/common/external_data_fetcher.h" 20#include "components/policy/core/common/mock_configuration_policy_provider.h" 21#include "components/policy/core/common/policy_map.h" 22#include "components/policy/core/common/policy_service_impl.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 64class FakeWebTrustedCertsObserver 65 : public UserNetworkConfigurationUpdater::WebTrustedCertsObserver { 66 public: 67 virtual void OnTrustAnchorsChanged( 68 const net::CertificateList& trust_anchors) OVERRIDE { 69 trust_anchors_ = trust_anchors; 70 } 71 net::CertificateList trust_anchors_; 72}; 73 74const char kFakeONC[] = 75 "{ \"NetworkConfigurations\": [" 76 " { \"GUID\": \"{485d6076-dd44-6b6d-69787465725f5040}\"," 77 " \"Type\": \"WiFi\"," 78 " \"Name\": \"My WiFi Network\"," 79 " \"WiFi\": {" 80 " \"SSID\": \"ssid-none\"," 81 " \"Security\": \"None\" }" 82 " }" 83 " ]," 84 " \"GlobalNetworkConfiguration\": {" 85 " \"AllowOnlyPolicyNetworksToAutoconnect\": true," 86 " }," 87 " \"Certificates\": [" 88 " { \"GUID\": \"{f998f760-272b-6939-4c2beffe428697ac}\"," 89 " \"PKCS12\": \"abc\"," 90 " \"Type\": \"Client\" }" 91 " ]," 92 " \"Type\": \"UnencryptedConfiguration\"" 93 "}"; 94 95std::string ValueToString(const base::Value& value) { 96 std::stringstream str; 97 str << value; 98 return str.str(); 99} 100 101void AppendAll(const base::ListValue& from, base::ListValue* to) { 102 for (base::ListValue::const_iterator it = from.begin(); it != from.end(); 103 ++it) { 104 to->Append((*it)->DeepCopy()); 105 } 106} 107 108// Matcher to match base::Value. 109MATCHER_P(IsEqualTo, 110 value, 111 std::string(negation ? "isn't" : "is") + " equal to " + 112 ValueToString(*value)) { 113 return value->Equals(&arg); 114} 115 116MATCHER(IsEmpty, std::string(negation ? "isn't" : "is") + " empty.") { 117 return arg.empty(); 118} 119 120ACTION_P(SetCertificateList, list) { 121 if (arg2) 122 *arg2 = list; 123 return true; 124} 125 126} // namespace 127 128class NetworkConfigurationUpdaterTest : public testing::Test { 129 protected: 130 NetworkConfigurationUpdaterTest() { 131 } 132 133 virtual void SetUp() OVERRIDE { 134 EXPECT_CALL(provider_, IsInitializationComplete(_)) 135 .WillRepeatedly(Return(true)); 136 provider_.Init(); 137 PolicyServiceImpl::Providers providers; 138 providers.push_back(&provider_); 139 policy_service_.reset(new PolicyServiceImpl( 140 providers, PolicyServiceImpl::PreprocessCallback())); 141 142 scoped_ptr<base::DictionaryValue> fake_toplevel_onc = 143 chromeos::onc::ReadDictionaryFromJson(kFakeONC); 144 145 base::ListValue* network_configs = NULL; 146 fake_toplevel_onc->GetListWithoutPathExpansion( 147 onc::toplevel_config::kNetworkConfigurations, &network_configs); 148 AppendAll(*network_configs, &fake_network_configs_); 149 150 base::DictionaryValue* global_config = NULL; 151 fake_toplevel_onc->GetDictionaryWithoutPathExpansion( 152 onc::toplevel_config::kGlobalNetworkConfiguration, &global_config); 153 fake_global_network_config_.MergeDictionary(global_config); 154 155 base::ListValue* certs = NULL; 156 fake_toplevel_onc->GetListWithoutPathExpansion( 157 onc::toplevel_config::kCertificates, &certs); 158 AppendAll(*certs, &fake_certificates_); 159 160 certificate_importer_ = 161 new StrictMock<chromeos::onc::MockCertificateImporter>(); 162 certificate_importer_owned_.reset(certificate_importer_); 163 } 164 165 virtual void TearDown() OVERRIDE { 166 network_configuration_updater_.reset(); 167 provider_.Shutdown(); 168 base::RunLoop().RunUntilIdle(); 169 } 170 171 void UpdateProviderPolicy(const PolicyMap& policy) { 172 provider_.UpdateChromePolicy(policy); 173 base::RunLoop().RunUntilIdle(); 174 } 175 176 UserNetworkConfigurationUpdater* 177 CreateNetworkConfigurationUpdaterForUserPolicy( 178 bool allow_trusted_certs_from_policy) { 179 UserNetworkConfigurationUpdater* updater = 180 UserNetworkConfigurationUpdater::CreateForUserPolicy( 181 allow_trusted_certs_from_policy, 182 fake_user_, 183 certificate_importer_owned_.Pass(), 184 policy_service_.get(), 185 &network_config_handler_).release(); 186 network_configuration_updater_.reset(updater); 187 return updater; 188 } 189 190 void CreateNetworkConfigurationUpdaterForDevicePolicy() { 191 network_configuration_updater_ = 192 NetworkConfigurationUpdater::CreateForDevicePolicy( 193 certificate_importer_owned_.Pass(), 194 policy_service_.get(), 195 &network_config_handler_); 196 } 197 198 base::ListValue fake_network_configs_; 199 base::DictionaryValue fake_global_network_config_; 200 base::ListValue fake_certificates_; 201 StrictMock<chromeos::MockManagedNetworkConfigurationHandler> 202 network_config_handler_; 203 204 // Ownership of certificate_importer_owned_ is passed to the 205 // NetworkConfigurationUpdater. When that happens, |certificate_importer_| 206 // continues to point to that instance but |certificate_importer_owned_| is 207 // released. 208 StrictMock<chromeos::onc::MockCertificateImporter>* certificate_importer_; 209 scoped_ptr<chromeos::onc::CertificateImporter> certificate_importer_owned_; 210 211 StrictMock<MockConfigurationPolicyProvider> provider_; 212 scoped_ptr<PolicyServiceImpl> policy_service_; 213 FakeUser fake_user_; 214 215 scoped_ptr<NetworkConfigurationUpdater> network_configuration_updater_; 216 content::TestBrowserThreadBundle thread_bundle_; 217}; 218 219TEST_F(NetworkConfigurationUpdaterTest, PolicyIsValidatedAndRepaired) { 220 scoped_ptr<base::DictionaryValue> onc_repaired = 221 chromeos::onc::test_utils::ReadTestDictionary( 222 "repaired_toplevel_partially_invalid.onc"); 223 224 base::ListValue* network_configs_repaired = NULL; 225 onc_repaired->GetListWithoutPathExpansion( 226 onc::toplevel_config::kNetworkConfigurations, &network_configs_repaired); 227 ASSERT_TRUE(network_configs_repaired); 228 229 base::DictionaryValue* global_config_repaired = NULL; 230 onc_repaired->GetDictionaryWithoutPathExpansion( 231 onc::toplevel_config::kGlobalNetworkConfiguration, 232 &global_config_repaired); 233 ASSERT_TRUE(global_config_repaired); 234 235 std::string onc_policy = 236 chromeos::onc::test_utils::ReadTestData("toplevel_partially_invalid.onc"); 237 PolicyMap policy; 238 policy.Set(key::kOpenNetworkConfiguration, 239 POLICY_LEVEL_MANDATORY, 240 POLICY_SCOPE_USER, 241 new base::StringValue(onc_policy), 242 NULL); 243 UpdateProviderPolicy(policy); 244 245 EXPECT_CALL(network_config_handler_, 246 SetPolicy(onc::ONC_SOURCE_USER_POLICY, 247 _, 248 IsEqualTo(network_configs_repaired), 249 IsEqualTo(global_config_repaired))); 250 EXPECT_CALL(*certificate_importer_, 251 ImportCertificates(_, onc::ONC_SOURCE_USER_POLICY, _)); 252 253 CreateNetworkConfigurationUpdaterForUserPolicy( 254 false /* do not allow trusted certs from policy */ ); 255} 256 257TEST_F(NetworkConfigurationUpdaterTest, 258 DoNotAllowTrustedCertificatesFromPolicy) { 259 net::CertificateList cert_list; 260 cert_list = 261 net::CreateCertificateListFromFile(net::GetTestCertsDirectory(), 262 "ok_cert.pem", 263 net::X509Certificate::FORMAT_AUTO); 264 ASSERT_EQ(1u, cert_list.size()); 265 266 EXPECT_CALL(network_config_handler_, 267 SetPolicy(onc::ONC_SOURCE_USER_POLICY, _, _, _)); 268 EXPECT_CALL(*certificate_importer_, ImportCertificates(_, _, _)) 269 .WillRepeatedly(SetCertificateList(cert_list)); 270 271 UserNetworkConfigurationUpdater* updater = 272 CreateNetworkConfigurationUpdaterForUserPolicy( 273 false /* do not allow trusted certs from policy */); 274 275 // Certificates with the "Web" trust flag set should not be forwarded to 276 // observers. 277 FakeWebTrustedCertsObserver observer; 278 updater->AddTrustedCertsObserver(&observer); 279 280 base::RunLoop().RunUntilIdle(); 281 282 net::CertificateList trust_anchors; 283 updater->GetWebTrustedCertificates(&trust_anchors); 284 EXPECT_TRUE(trust_anchors.empty()); 285 286 EXPECT_TRUE(observer.trust_anchors_.empty()); 287 updater->RemoveTrustedCertsObserver(&observer); 288} 289 290TEST_F(NetworkConfigurationUpdaterTest, 291 AllowTrustedCertificatesFromPolicyInitially) { 292 // Ignore network configuration changes. 293 EXPECT_CALL(network_config_handler_, SetPolicy(_, _, _, _)) 294 .Times(AnyNumber()); 295 296 net::CertificateList cert_list; 297 cert_list = 298 net::CreateCertificateListFromFile(net::GetTestCertsDirectory(), 299 "ok_cert.pem", 300 net::X509Certificate::FORMAT_AUTO); 301 ASSERT_EQ(1u, cert_list.size()); 302 303 EXPECT_CALL(*certificate_importer_, 304 ImportCertificates(_, onc::ONC_SOURCE_USER_POLICY, _)) 305 .WillRepeatedly(SetCertificateList(cert_list)); 306 307 UserNetworkConfigurationUpdater* updater = 308 CreateNetworkConfigurationUpdaterForUserPolicy( 309 true /* allow trusted certs from policy */); 310 311 base::RunLoop().RunUntilIdle(); 312 313 // Certificates with the "Web" trust flag set will be returned. 314 net::CertificateList trust_anchors; 315 updater->GetWebTrustedCertificates(&trust_anchors); 316 EXPECT_EQ(1u, trust_anchors.size()); 317} 318 319TEST_F(NetworkConfigurationUpdaterTest, 320 AllowTrustedCertificatesFromPolicyOnUpdate) { 321 // Ignore network configuration changes. 322 EXPECT_CALL(network_config_handler_, SetPolicy(_, _, _, _)) 323 .Times(AnyNumber()); 324 325 // Start with an empty certificate list. 326 EXPECT_CALL(*certificate_importer_, 327 ImportCertificates(_, onc::ONC_SOURCE_USER_POLICY, _)) 328 .WillRepeatedly(SetCertificateList(net::CertificateList())); 329 330 UserNetworkConfigurationUpdater* updater = 331 CreateNetworkConfigurationUpdaterForUserPolicy( 332 true /* allow trusted certs from policy */); 333 334 FakeWebTrustedCertsObserver observer; 335 updater->AddTrustedCertsObserver(&observer); 336 337 base::RunLoop().RunUntilIdle(); 338 339 // Verify that the returned certificate list is empty. 340 Mock::VerifyAndClearExpectations(certificate_importer_); 341 { 342 net::CertificateList trust_anchors; 343 updater->GetWebTrustedCertificates(&trust_anchors); 344 EXPECT_TRUE(trust_anchors.empty()); 345 } 346 EXPECT_TRUE(observer.trust_anchors_.empty()); 347 348 // Now use a non-empty certificate list to test the observer notification. 349 net::CertificateList cert_list; 350 cert_list = 351 net::CreateCertificateListFromFile(net::GetTestCertsDirectory(), 352 "ok_cert.pem", 353 net::X509Certificate::FORMAT_AUTO); 354 ASSERT_EQ(1u, cert_list.size()); 355 356 EXPECT_CALL(*certificate_importer_, 357 ImportCertificates(_, onc::ONC_SOURCE_USER_POLICY, _)) 358 .WillOnce(SetCertificateList(cert_list)); 359 360 // Change to any non-empty policy, so that updates are triggered. The actual 361 // content of the policy is irrelevant. 362 PolicyMap policy; 363 policy.Set(key::kOpenNetworkConfiguration, 364 POLICY_LEVEL_MANDATORY, 365 POLICY_SCOPE_USER, 366 new base::StringValue(kFakeONC), 367 NULL); 368 UpdateProviderPolicy(policy); 369 base::RunLoop().RunUntilIdle(); 370 371 // Certificates with the "Web" trust flag set will be returned and forwarded 372 // to observers. 373 { 374 net::CertificateList trust_anchors; 375 updater->GetWebTrustedCertificates(&trust_anchors); 376 EXPECT_EQ(1u, trust_anchors.size()); 377 } 378 EXPECT_EQ(1u, observer.trust_anchors_.size()); 379 380 updater->RemoveTrustedCertsObserver(&observer); 381} 382 383class NetworkConfigurationUpdaterTestWithParam 384 : public NetworkConfigurationUpdaterTest, 385 public testing::WithParamInterface<const char*> { 386 protected: 387 // Returns the currently tested ONC source. 388 onc::ONCSource CurrentONCSource() { 389 if (GetParam() == key::kOpenNetworkConfiguration) 390 return onc::ONC_SOURCE_USER_POLICY; 391 DCHECK(GetParam() == key::kDeviceOpenNetworkConfiguration); 392 return onc::ONC_SOURCE_DEVICE_POLICY; 393 } 394 395 // Returns the expected username hash to push policies to 396 // ManagedNetworkConfigurationHandler. 397 std::string ExpectedUsernameHash() { 398 if (GetParam() == key::kOpenNetworkConfiguration) 399 return kFakeUsernameHash; 400 return std::string(); 401 } 402 403 void CreateNetworkConfigurationUpdater() { 404 if (GetParam() == key::kOpenNetworkConfiguration) { 405 CreateNetworkConfigurationUpdaterForUserPolicy( 406 false /* do not allow trusted certs from policy */); 407 } else { 408 CreateNetworkConfigurationUpdaterForDevicePolicy(); 409 } 410 } 411}; 412 413TEST_P(NetworkConfigurationUpdaterTestWithParam, InitialUpdates) { 414 PolicyMap policy; 415 policy.Set(GetParam(), POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, 416 new base::StringValue(kFakeONC), NULL); 417 UpdateProviderPolicy(policy); 418 419 EXPECT_CALL(network_config_handler_, 420 SetPolicy(CurrentONCSource(), 421 ExpectedUsernameHash(), 422 IsEqualTo(&fake_network_configs_), 423 IsEqualTo(&fake_global_network_config_))); 424 EXPECT_CALL(*certificate_importer_, 425 ImportCertificates( 426 IsEqualTo(&fake_certificates_), CurrentONCSource(), _)); 427 428 CreateNetworkConfigurationUpdater(); 429} 430 431 432TEST_P(NetworkConfigurationUpdaterTestWithParam, PolicyChange) { 433 // Ignore the initial updates. 434 EXPECT_CALL(network_config_handler_, SetPolicy(_, _, _, _)).Times(AtLeast(1)); 435 EXPECT_CALL(*certificate_importer_, ImportCertificates(_, _, _)) 436 .Times(AtLeast(1)); 437 CreateNetworkConfigurationUpdater(); 438 Mock::VerifyAndClearExpectations(&network_config_handler_); 439 Mock::VerifyAndClearExpectations(certificate_importer_); 440 441 // The Updater should update if policy changes. 442 EXPECT_CALL(network_config_handler_, 443 SetPolicy(CurrentONCSource(), 444 _, 445 IsEqualTo(&fake_network_configs_), 446 IsEqualTo(&fake_global_network_config_))); 447 EXPECT_CALL(*certificate_importer_, 448 ImportCertificates( 449 IsEqualTo(&fake_certificates_), CurrentONCSource(), _)); 450 451 PolicyMap policy; 452 policy.Set(GetParam(), POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, 453 new base::StringValue(kFakeONC), NULL); 454 UpdateProviderPolicy(policy); 455 Mock::VerifyAndClearExpectations(&network_config_handler_); 456 Mock::VerifyAndClearExpectations(certificate_importer_); 457 458 // Another update is expected if the policy goes away. 459 EXPECT_CALL(network_config_handler_, 460 SetPolicy(CurrentONCSource(), _, IsEmpty(), IsEmpty())); 461 EXPECT_CALL(*certificate_importer_, 462 ImportCertificates(IsEmpty(), CurrentONCSource(), _)); 463 464 policy.Erase(GetParam()); 465 UpdateProviderPolicy(policy); 466} 467 468INSTANTIATE_TEST_CASE_P(NetworkConfigurationUpdaterTestWithParamInstance, 469 NetworkConfigurationUpdaterTestWithParam, 470 testing::Values(key::kDeviceOpenNetworkConfiguration, 471 key::kOpenNetworkConfiguration)); 472 473} // namespace policy 474