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