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