Home | History | Annotate | Download | only in policy
      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 "chrome/browser/chromeos/policy/network_configuration_updater_impl_cros.h"
      6 
      7 #include "base/callback.h"
      8 #include "base/files/file_path.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/run_loop.h"
     12 #include "base/values.h"
     13 #include "chrome/browser/chromeos/cros/mock_network_library.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/onc/mock_certificate_importer.h"
     19 #include "chromeos/network/onc/onc_constants.h"
     20 #include "chromeos/network/onc/onc_test_utils.h"
     21 #include "chromeos/network/onc/onc_utils.h"
     22 #include "content/public/test/test_browser_thread.h"
     23 #include "content/public/test/test_utils.h"
     24 #include "net/base/test_data_directory.h"
     25 #include "net/cert/cert_trust_anchor_provider.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 
     32 using testing::AnyNumber;
     33 using testing::Mock;
     34 using testing::Ne;
     35 using testing::Return;
     36 using testing::StrictMock;
     37 using testing::_;
     38 
     39 namespace onc = ::chromeos::onc;
     40 
     41 namespace policy {
     42 
     43 namespace {
     44 
     45 const char kFakeONC[] =
     46     "{ \"NetworkConfigurations\": ["
     47     "    { \"GUID\": \"{485d6076-dd44-6b6d-69787465725f5040}\","
     48     "      \"Type\": \"WiFi\","
     49     "      \"Name\": \"My WiFi Network\","
     50     "      \"WiFi\": {"
     51     "        \"SSID\": \"ssid-none\","
     52     "        \"Security\": \"None\" }"
     53     "    }"
     54     "  ],"
     55     "  \"Certificates\": ["
     56     "    { \"GUID\": \"{f998f760-272b-6939-4c2beffe428697ac}\","
     57     "      \"PKCS12\": \"abc\","
     58     "       \"Type\": \"Client\" }"
     59     "  ],"
     60     "  \"Type\": \"UnencryptedConfiguration\""
     61     "}";
     62 
     63 std::string ValueToString(const base::Value* value) {
     64     std::stringstream str;
     65     str << *value;
     66     return str.str();
     67 }
     68 
     69 // Matcher to match base::Value.
     70 MATCHER_P(IsEqualTo,
     71           value,
     72           std::string(negation ? "isn't" : "is") + " equal to " +
     73           ValueToString(value)) {
     74   return value->Equals(&arg);
     75 }
     76 
     77 ACTION_P(SetCertificateList, list) {
     78   *arg2 = list;
     79   return true;
     80 }
     81 
     82 ACTION_P(SetImportedCerts, map) {
     83   *arg3 = map;
     84   return true;
     85 }
     86 
     87 }  // namespace
     88 
     89 // Tests of NetworkConfigurationUpdaterImplCros
     90 class NetworkConfigurationUpdaterTest : public testing::Test {
     91  protected:
     92   NetworkConfigurationUpdaterTest()
     93       : ui_thread_(content::BrowserThread::UI, &loop_),
     94         io_thread_(content::BrowserThread::IO, &loop_) {}
     95 
     96   virtual void SetUp() OVERRIDE {
     97     EXPECT_CALL(provider_, IsInitializationComplete(_))
     98         .WillRepeatedly(Return(true));
     99     provider_.Init();
    100     PolicyServiceImpl::Providers providers;
    101     providers.push_back(&provider_);
    102     policy_service_.reset(new PolicyServiceImpl(providers));
    103 
    104     empty_network_configs_.reset(new base::ListValue);
    105     empty_certificates_.reset(new base::ListValue);
    106 
    107     scoped_ptr<base::DictionaryValue> fake_toplevel_onc =
    108         onc::ReadDictionaryFromJson(kFakeONC);
    109 
    110     scoped_ptr<base::Value> network_configs_value;
    111     base::ListValue* network_configs = NULL;
    112     fake_toplevel_onc->RemoveWithoutPathExpansion(
    113         onc::toplevel_config::kNetworkConfigurations,
    114         &network_configs_value);
    115     network_configs_value.release()->GetAsList(&network_configs);
    116     fake_network_configs_.reset(network_configs);
    117 
    118     scoped_ptr<base::Value> certs_value;
    119     base::ListValue* certs = NULL;
    120     fake_toplevel_onc->RemoveWithoutPathExpansion(
    121         onc::toplevel_config::kCertificates,
    122         &certs_value);
    123     certs_value.release()->GetAsList(&certs);
    124     fake_certificates_.reset(certs);
    125   }
    126 
    127   virtual void TearDown() OVERRIDE {
    128     provider_.Shutdown();
    129     content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
    130   }
    131 
    132   void UpdateProviderPolicy(const PolicyMap& policy) {
    133     provider_.UpdateChromePolicy(policy);
    134     base::RunLoop loop;
    135     loop.RunUntilIdle();
    136   }
    137 
    138   // Maps configuration policy name to corresponding ONC source.
    139   static onc::ONCSource NameToONCSource(
    140       const std::string& name) {
    141     if (name == key::kDeviceOpenNetworkConfiguration)
    142       return onc::ONC_SOURCE_DEVICE_POLICY;
    143     if (name == key::kOpenNetworkConfiguration)
    144       return onc::ONC_SOURCE_USER_POLICY;
    145     return onc::ONC_SOURCE_NONE;
    146   }
    147 
    148   scoped_ptr<base::ListValue> empty_network_configs_;
    149   scoped_ptr<base::ListValue> empty_certificates_;
    150   scoped_ptr<base::ListValue> fake_network_configs_;
    151   scoped_ptr<base::ListValue> fake_certificates_;
    152   StrictMock<chromeos::MockNetworkLibrary> network_library_;
    153   StrictMock<MockConfigurationPolicyProvider> provider_;
    154   scoped_ptr<PolicyServiceImpl> policy_service_;
    155   base::MessageLoop loop_;
    156   content::TestBrowserThread ui_thread_;
    157   content::TestBrowserThread io_thread_;
    158 };
    159 
    160 TEST_F(NetworkConfigurationUpdaterTest, PolicyIsValidatedAndRepaired) {
    161   std::string onc_policy =
    162       onc::test_utils::ReadTestData("toplevel_partially_invalid.onc");
    163 
    164   scoped_ptr<base::DictionaryValue> onc_repaired =
    165       onc::test_utils::ReadTestDictionary(
    166           "repaired_toplevel_partially_invalid.onc");
    167 
    168   base::ListValue* network_configs_repaired = NULL;
    169   onc_repaired->GetListWithoutPathExpansion(
    170       onc::toplevel_config::kNetworkConfigurations,
    171       &network_configs_repaired);
    172   ASSERT_TRUE(network_configs_repaired);
    173 
    174   PolicyMap policy;
    175   policy.Set(key::kOpenNetworkConfiguration, POLICY_LEVEL_MANDATORY,
    176              POLICY_SCOPE_USER, Value::CreateStringValue(onc_policy), NULL);
    177   UpdateProviderPolicy(policy);
    178 
    179   EXPECT_CALL(network_library_, AddNetworkProfileObserver(_));
    180 
    181   // Ignore the device policy update.
    182   EXPECT_CALL(network_library_, LoadOncNetworks(_, _));
    183   StrictMock<chromeos::onc::MockCertificateImporter>* certificate_importer =
    184       new StrictMock<chromeos::onc::MockCertificateImporter>();
    185   EXPECT_CALL(*certificate_importer, ImportCertificates(_, _, _));
    186 
    187   NetworkConfigurationUpdaterImplCros updater(
    188       policy_service_.get(),
    189       &network_library_,
    190       make_scoped_ptr<chromeos::onc::CertificateImporter>(
    191           certificate_importer));
    192   Mock::VerifyAndClearExpectations(&network_library_);
    193   Mock::VerifyAndClearExpectations(&certificate_importer);
    194 
    195   // After the user policy is initialized, we always push both policies to the
    196   // NetworkLibrary. Ignore the device policy.
    197   EXPECT_CALL(network_library_, LoadOncNetworks(
    198       _, onc::ONC_SOURCE_DEVICE_POLICY));
    199   EXPECT_CALL(network_library_, LoadOncNetworks(
    200       IsEqualTo(network_configs_repaired),
    201       onc::ONC_SOURCE_USER_POLICY));
    202   EXPECT_CALL(*certificate_importer,
    203               ImportCertificates(_, chromeos::onc::ONC_SOURCE_DEVICE_POLICY,
    204                                  _));
    205   EXPECT_CALL(*certificate_importer,
    206               ImportCertificates(_, chromeos::onc::ONC_SOURCE_USER_POLICY,
    207                                  _));
    208 
    209   EXPECT_CALL(network_library_, RemoveNetworkProfileObserver(_));
    210 
    211   updater.SetUserPolicyService(false, "hash", policy_service_.get());
    212   updater.UnsetUserPolicyService();
    213 }
    214 
    215 class NetworkConfigurationUpdaterTestWithParam
    216     : public NetworkConfigurationUpdaterTest,
    217       public testing::WithParamInterface<const char*> {
    218 };
    219 
    220 TEST_P(NetworkConfigurationUpdaterTestWithParam, InitialUpdates) {
    221   PolicyMap policy;
    222   policy.Set(GetParam(), POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
    223              Value::CreateStringValue(kFakeONC), NULL);
    224   UpdateProviderPolicy(policy);
    225 
    226   EXPECT_CALL(network_library_, AddNetworkProfileObserver(_));
    227 
    228   // Initially, only the device policy is applied. The user policy is only
    229   // applied after the user profile was initialized.
    230   base::ListValue* device_networks;
    231   base::ListValue* device_certs;
    232   base::ListValue* user_networks;
    233   base::ListValue* user_certs;
    234   if (GetParam() == key::kDeviceOpenNetworkConfiguration) {
    235     device_networks = fake_network_configs_.get();
    236     device_certs = fake_certificates_.get();
    237     user_networks = empty_network_configs_.get();
    238     user_certs = empty_certificates_.get();
    239   } else {
    240     device_networks = empty_network_configs_.get();
    241     device_certs = empty_certificates_.get();
    242     user_networks = fake_network_configs_.get();
    243     user_certs = fake_certificates_.get();
    244   }
    245 
    246   EXPECT_CALL(network_library_, LoadOncNetworks(
    247       IsEqualTo(device_networks), onc::ONC_SOURCE_DEVICE_POLICY));
    248   StrictMock<chromeos::onc::MockCertificateImporter>* certificate_importer =
    249       new StrictMock<chromeos::onc::MockCertificateImporter>();
    250   EXPECT_CALL(*certificate_importer, ImportCertificates(
    251       IsEqualTo(device_certs), onc::ONC_SOURCE_DEVICE_POLICY, _));
    252 
    253   NetworkConfigurationUpdaterImplCros updater(
    254       policy_service_.get(),
    255       &network_library_,
    256       make_scoped_ptr<chromeos::onc::CertificateImporter>(
    257           certificate_importer));
    258   Mock::VerifyAndClearExpectations(&network_library_);
    259   Mock::VerifyAndClearExpectations(&certificate_importer);
    260 
    261   // After the user policy is initialized, we always push both policies to the
    262   // NetworkLibrary.
    263   EXPECT_CALL(network_library_, LoadOncNetworks(
    264       IsEqualTo(device_networks), onc::ONC_SOURCE_DEVICE_POLICY));
    265   EXPECT_CALL(*certificate_importer, ImportCertificates(
    266       IsEqualTo(device_certs), onc::ONC_SOURCE_DEVICE_POLICY, _));
    267 
    268   EXPECT_CALL(network_library_, LoadOncNetworks(
    269       IsEqualTo(user_networks), onc::ONC_SOURCE_USER_POLICY));
    270   EXPECT_CALL(*certificate_importer, ImportCertificates(
    271       IsEqualTo(user_certs), onc::ONC_SOURCE_USER_POLICY, _));
    272 
    273   EXPECT_CALL(network_library_, RemoveNetworkProfileObserver(_));
    274 
    275   // We just need an initialized PolicyService, so we can reuse
    276   // |policy_service_|.
    277   updater.SetUserPolicyService(false, "hash", policy_service_.get());
    278   updater.UnsetUserPolicyService();
    279 }
    280 
    281 TEST_P(NetworkConfigurationUpdaterTestWithParam,
    282        AllowTrustedCertificatesFromPolicy) {
    283   EXPECT_CALL(network_library_, AddNetworkProfileObserver(_));
    284 
    285   const net::CertificateList empty_cert_list;
    286 
    287   const net::CertificateList cert_list =
    288       net::CreateCertificateListFromFile(net::GetTestCertsDirectory(),
    289                                          "ok_cert.pem",
    290                                          net::X509Certificate::FORMAT_AUTO);
    291   ASSERT_EQ(1u, cert_list.size());
    292 
    293   EXPECT_CALL(network_library_, LoadOncNetworks(_, _)).Times(AnyNumber());
    294   StrictMock<chromeos::onc::MockCertificateImporter>* certificate_importer =
    295       new StrictMock<chromeos::onc::MockCertificateImporter>();
    296   EXPECT_CALL(*certificate_importer, ImportCertificates(_, _, _))
    297       .WillRepeatedly(SetCertificateList(empty_cert_list));
    298   NetworkConfigurationUpdaterImplCros updater(
    299       policy_service_.get(),
    300       &network_library_,
    301       make_scoped_ptr<chromeos::onc::CertificateImporter>(
    302           certificate_importer));
    303   net::CertTrustAnchorProvider* trust_provider =
    304       updater.GetCertTrustAnchorProvider();
    305   ASSERT_TRUE(trust_provider);
    306   // The initial list of trust anchors is empty.
    307   content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
    308   EXPECT_TRUE(trust_provider->GetAdditionalTrustAnchors().empty());
    309 
    310   // Initially, certificates imported from policy don't have trust flags.
    311   updater.SetUserPolicyService(false, "hash", policy_service_.get());
    312   content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
    313   Mock::VerifyAndClearExpectations(&network_library_);
    314   Mock::VerifyAndClearExpectations(&certificate_importer);
    315   EXPECT_TRUE(trust_provider->GetAdditionalTrustAnchors().empty());
    316 
    317   // Certificates with the "Web" trust flag set should be forwarded to the
    318   // trust provider.
    319   EXPECT_CALL(network_library_, LoadOncNetworks(_, _));
    320   EXPECT_CALL(*certificate_importer, ImportCertificates(_, _, _))
    321       .WillRepeatedly(SetCertificateList(empty_cert_list));
    322   onc::ONCSource current_source = NameToONCSource(GetParam());
    323   EXPECT_CALL(network_library_, LoadOncNetworks(_, current_source));
    324   EXPECT_CALL(*certificate_importer, ImportCertificates(_, current_source, _))
    325       .WillRepeatedly(SetCertificateList(cert_list));
    326   // Trigger a new policy load, and spin the IO message loop to pass the
    327   // certificates to the |trust_provider| on the IO thread.
    328   updater.SetUserPolicyService(true, "hash", policy_service_.get());
    329   base::RunLoop loop;
    330   loop.RunUntilIdle();
    331   Mock::VerifyAndClearExpectations(&network_library_);
    332   Mock::VerifyAndClearExpectations(&certificate_importer);
    333 
    334   // Certificates are only provided as trust anchors if they come from user
    335   // policy.
    336   size_t expected_certs = 0u;
    337   if (GetParam() == key::kOpenNetworkConfiguration)
    338     expected_certs = 1u;
    339   EXPECT_EQ(expected_certs,
    340             trust_provider->GetAdditionalTrustAnchors().size());
    341 
    342   EXPECT_CALL(network_library_, RemoveNetworkProfileObserver(_));
    343   updater.UnsetUserPolicyService();
    344 }
    345 
    346 TEST_P(NetworkConfigurationUpdaterTestWithParam, PolicyChange) {
    347   EXPECT_CALL(network_library_, AddNetworkProfileObserver(_));
    348 
    349   // Ignore the initial updates.
    350   EXPECT_CALL(network_library_, LoadOncNetworks(_, _))
    351       .Times(AnyNumber());
    352   StrictMock<chromeos::onc::MockCertificateImporter>* certificate_importer =
    353       new StrictMock<chromeos::onc::MockCertificateImporter>();
    354   EXPECT_CALL(*certificate_importer, ImportCertificates(_, _, _))
    355       .Times(AnyNumber());
    356   NetworkConfigurationUpdaterImplCros updater(
    357       policy_service_.get(),
    358       &network_library_,
    359       make_scoped_ptr<chromeos::onc::CertificateImporter>(
    360           certificate_importer));
    361   updater.SetUserPolicyService(false, "hash", policy_service_.get());
    362   Mock::VerifyAndClearExpectations(&network_library_);
    363   Mock::VerifyAndClearExpectations(&certificate_importer);
    364 
    365   // We should update if policy changes.
    366   EXPECT_CALL(network_library_, LoadOncNetworks(
    367       IsEqualTo(fake_network_configs_.get()), NameToONCSource(GetParam())));
    368   EXPECT_CALL(*certificate_importer, ImportCertificates(
    369       IsEqualTo(fake_certificates_.get()), NameToONCSource(GetParam()), _));
    370 
    371   // In the current implementation, we always apply both policies.
    372   EXPECT_CALL(network_library_, LoadOncNetworks(
    373       IsEqualTo(empty_network_configs_.get()),
    374       Ne(NameToONCSource(GetParam()))));
    375   EXPECT_CALL(*certificate_importer, ImportCertificates(
    376       IsEqualTo(empty_certificates_.get()),
    377       Ne(NameToONCSource(GetParam())),
    378       _));
    379 
    380   PolicyMap policy;
    381   policy.Set(GetParam(), POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
    382              Value::CreateStringValue(kFakeONC), NULL);
    383   UpdateProviderPolicy(policy);
    384   Mock::VerifyAndClearExpectations(&network_library_);
    385   Mock::VerifyAndClearExpectations(&certificate_importer);
    386 
    387   // Another update is expected if the policy goes away. In the current
    388   // implementation, we always apply both policies.
    389   EXPECT_CALL(network_library_, LoadOncNetworks(
    390       IsEqualTo(empty_network_configs_.get()),
    391       onc::ONC_SOURCE_DEVICE_POLICY));
    392   EXPECT_CALL(*certificate_importer, ImportCertificates(
    393       IsEqualTo(empty_certificates_.get()),
    394       onc::ONC_SOURCE_DEVICE_POLICY,
    395       _));
    396 
    397   EXPECT_CALL(network_library_, LoadOncNetworks(
    398       IsEqualTo(empty_network_configs_.get()),
    399       onc::ONC_SOURCE_USER_POLICY));
    400   EXPECT_CALL(*certificate_importer, ImportCertificates(
    401       IsEqualTo(empty_certificates_.get()),
    402       onc::ONC_SOURCE_USER_POLICY,
    403       _));
    404 
    405   EXPECT_CALL(network_library_, RemoveNetworkProfileObserver(_));
    406 
    407   policy.Erase(GetParam());
    408   UpdateProviderPolicy(policy);
    409   updater.UnsetUserPolicyService();
    410 }
    411 
    412 INSTANTIATE_TEST_CASE_P(
    413     NetworkConfigurationUpdaterTestWithParamInstance,
    414     NetworkConfigurationUpdaterTestWithParam,
    415     testing::Values(key::kDeviceOpenNetworkConfiguration,
    416                     key::kOpenNetworkConfiguration));
    417 
    418 }  // namespace policy
    419