Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chromeos / network / auto_connect_handler_unittest.cc
bloba52f60e53dfcdc8dde935e7ee784410e893aed51
1 // Copyright 2014 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.
5 #include "chromeos/network/auto_connect_handler.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/files/file_util.h"
12 #include "base/json/json_reader.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/run_loop.h"
16 #include "base/strings/stringprintf.h"
17 #include "chromeos/cert_loader.h"
18 #include "chromeos/dbus/dbus_thread_manager.h"
19 #include "chromeos/dbus/shill_device_client.h"
20 #include "chromeos/dbus/shill_manager_client.h"
21 #include "chromeos/dbus/shill_profile_client.h"
22 #include "chromeos/dbus/shill_service_client.h"
23 #include "chromeos/network/client_cert_resolver.h"
24 #include "chromeos/network/managed_network_configuration_handler_impl.h"
25 #include "chromeos/network/network_configuration_handler.h"
26 #include "chromeos/network/network_profile_handler.h"
27 #include "chromeos/network/network_state_handler.h"
28 #include "chromeos/network/onc/onc_utils.h"
29 #include "components/onc/onc_constants.h"
30 #include "crypto/scoped_nss_types.h"
31 #include "crypto/scoped_test_nss_db.h"
32 #include "net/base/net_errors.h"
33 #include "net/base/test_data_directory.h"
34 #include "net/cert/nss_cert_database_chromeos.h"
35 #include "net/cert/x509_certificate.h"
36 #include "net/test/cert_test_util.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38 #include "third_party/cros_system_api/dbus/service_constants.h"
40 namespace chromeos {
42 namespace {
44 const char* kUserHash = "user_hash";
46 void ConfigureCallback(const dbus::ObjectPath& result) {
49 void FailErrorCallback(const std::string& error_name,
50 const std::string& error_message) {
51 // This function is not expected to be called.
52 EXPECT_TRUE(false);
55 class TestCertResolveObserver : public ClientCertResolver::Observer {
56 public:
57 explicit TestCertResolveObserver(ClientCertResolver* cert_resolver)
58 : changed_network_properties_(false), cert_resolver_(cert_resolver) {
59 cert_resolver_->AddObserver(this);
62 void ResolveRequestCompleted(bool changed_network_properties) override {
63 cert_resolver_->RemoveObserver(this);
64 changed_network_properties_ = changed_network_properties;
67 bool DidNetworkPropertiesChange() { return changed_network_properties_; }
69 private:
70 bool changed_network_properties_;
71 ClientCertResolver* cert_resolver_;
74 } // namespace
76 class AutoConnectHandlerTest : public testing::Test {
77 public:
78 AutoConnectHandlerTest()
79 : test_manager_client_(nullptr), test_service_client_(nullptr) {}
81 void SetUp() override {
82 ASSERT_TRUE(test_nssdb_.is_open());
84 // Use the same DB for public and private slot.
85 test_nsscertdb_.reset(new net::NSSCertDatabaseChromeOS(
86 crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot())),
87 crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot()))));
88 test_nsscertdb_->SetSlowTaskRunnerForTest(message_loop_.task_runner());
90 CertLoader::Initialize();
91 CertLoader::ForceHardwareBackedForTesting();
93 DBusThreadManager::Initialize();
94 DBusThreadManager* dbus_manager = DBusThreadManager::Get();
95 test_manager_client_ =
96 dbus_manager->GetShillManagerClient()->GetTestInterface();
97 test_service_client_ =
98 dbus_manager->GetShillServiceClient()->GetTestInterface();
100 test_manager_client_->AddTechnology(shill::kTypeWifi, true /* enabled */);
101 dbus_manager->GetShillDeviceClient()->GetTestInterface()->AddDevice(
102 "/device/wifi1", shill::kTypeWifi, "wifi_device1");
103 test_manager_client_->AddTechnology(shill::kTypeCellular,
104 true /* enabled */);
105 dbus_manager->GetShillProfileClient()->GetTestInterface()->AddProfile(
106 "shared_profile_path", std::string() /* shared profile */);
107 dbus_manager->GetShillProfileClient()->GetTestInterface()->AddProfile(
108 "user_profile_path", kUserHash);
110 base::RunLoop().RunUntilIdle();
111 LoginState::Initialize();
112 network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
113 network_config_handler_.reset(
114 NetworkConfigurationHandler::InitializeForTest(
115 network_state_handler_.get(), NULL /* network_device_handler */));
117 network_profile_handler_.reset(new NetworkProfileHandler());
118 network_profile_handler_->Init();
120 managed_config_handler_.reset(new ManagedNetworkConfigurationHandlerImpl());
121 managed_config_handler_->Init(
122 network_state_handler_.get(), network_profile_handler_.get(),
123 network_config_handler_.get(), nullptr /* network_device_handler */);
125 client_cert_resolver_.reset(new ClientCertResolver());
126 client_cert_resolver_->Init(network_state_handler_.get(),
127 managed_config_handler_.get());
128 client_cert_resolver_->SetSlowTaskRunnerForTest(
129 message_loop_.task_runner());
131 auto_connect_handler_.reset(new AutoConnectHandler());
132 auto_connect_handler_->Init(client_cert_resolver_.get(),
133 nullptr, // no connection handler
134 network_state_handler_.get(),
135 managed_config_handler_.get());
137 base::RunLoop().RunUntilIdle();
140 void TearDown() override {
141 auto_connect_handler_.reset();
142 client_cert_resolver_.reset();
143 managed_config_handler_.reset();
144 network_profile_handler_.reset();
145 network_config_handler_.reset();
146 network_state_handler_.reset();
147 CertLoader::Shutdown();
148 LoginState::Shutdown();
149 DBusThreadManager::Shutdown();
152 protected:
153 bool Configure(const std::string& json_string) {
154 scoped_ptr<base::DictionaryValue> json_dict =
155 onc::ReadDictionaryFromJson(json_string);
156 if (!json_dict) {
157 LOG(ERROR) << "Error parsing json: " << json_string;
158 return false;
160 DBusThreadManager::Get()->GetShillManagerClient()->ConfigureService(
161 *json_dict, base::Bind(&ConfigureCallback),
162 base::Bind(&FailErrorCallback));
163 base::RunLoop().RunUntilIdle();
164 return true;
167 std::string GetServiceState(const std::string& service_path) {
168 const base::DictionaryValue* properties =
169 test_service_client_->GetServiceProperties(service_path);
170 std::string result;
171 if (properties)
172 properties->GetStringWithoutPathExpansion(shill::kStateProperty, &result);
173 return result;
176 void StartCertLoader() {
177 CertLoader::Get()->StartWithNSSDB(test_nsscertdb_.get());
178 base::RunLoop().RunUntilIdle();
181 void LoginToRegularUser() {
182 LoginState::Get()->SetLoggedInState(LoginState::LOGGED_IN_ACTIVE,
183 LoginState::LOGGED_IN_USER_REGULAR);
184 base::RunLoop().RunUntilIdle();
187 scoped_refptr<net::X509Certificate> ImportTestClientCert() {
188 net::CertificateList ca_cert_list = net::CreateCertificateListFromFile(
189 net::GetTestCertsDirectory(), "client_1_ca.pem",
190 net::X509Certificate::FORMAT_AUTO);
191 if (ca_cert_list.empty()) {
192 LOG(ERROR) << "No CA cert loaded.";
193 return nullptr;
195 net::NSSCertDatabase::ImportCertFailureList failures;
196 EXPECT_TRUE(test_nsscertdb_->ImportCACerts(
197 ca_cert_list, net::NSSCertDatabase::TRUST_DEFAULT, &failures));
198 if (!failures.empty()) {
199 LOG(ERROR) << net::ErrorToString(failures[0].net_error);
200 return nullptr;
203 // Import a client cert signed by that CA.
204 scoped_refptr<net::X509Certificate> client_cert(
205 net::ImportClientCertAndKeyFromFile(net::GetTestCertsDirectory(),
206 "client_1.pem", "client_1.pk8",
207 test_nssdb_.slot()));
208 return client_cert;
211 void SetupPolicy(const std::string& network_configs_json,
212 const base::DictionaryValue& global_config,
213 bool user_policy) {
214 scoped_ptr<base::ListValue> network_configs(new base::ListValue);
215 if (!network_configs_json.empty()) {
216 std::string error;
217 base::Value* network_configs_value =
218 base::JSONReader::DeprecatedReadAndReturnError(
219 network_configs_json, base::JSON_ALLOW_TRAILING_COMMAS, nullptr,
220 &error);
221 ASSERT_TRUE(network_configs_value) << error;
222 base::ListValue* network_configs_list = nullptr;
223 ASSERT_TRUE(network_configs_value->GetAsList(&network_configs_list));
224 network_configs.reset(network_configs_list);
227 if (user_policy) {
228 managed_config_handler_->SetPolicy(::onc::ONC_SOURCE_USER_POLICY,
229 kUserHash, *network_configs,
230 global_config);
231 } else {
232 managed_config_handler_->SetPolicy(::onc::ONC_SOURCE_DEVICE_POLICY,
233 std::string(), // no username hash
234 *network_configs, global_config);
236 base::RunLoop().RunUntilIdle();
239 scoped_ptr<AutoConnectHandler> auto_connect_handler_;
240 scoped_ptr<ClientCertResolver> client_cert_resolver_;
241 scoped_ptr<NetworkStateHandler> network_state_handler_;
242 scoped_ptr<NetworkConfigurationHandler> network_config_handler_;
243 scoped_ptr<ManagedNetworkConfigurationHandlerImpl> managed_config_handler_;
244 scoped_ptr<NetworkProfileHandler> network_profile_handler_;
245 ShillManagerClient::TestInterface* test_manager_client_;
246 ShillServiceClient::TestInterface* test_service_client_;
247 crypto::ScopedTestNSSDB test_nssdb_;
248 scoped_ptr<net::NSSCertDatabaseChromeOS> test_nsscertdb_;
249 base::MessageLoopForUI message_loop_;
251 private:
252 DISALLOW_COPY_AND_ASSIGN(AutoConnectHandlerTest);
255 namespace {
257 const char* kConfigUnmanagedSharedConnected =
258 "{ \"GUID\": \"wifi0\", \"Type\": \"wifi\", \"State\": \"online\", "
259 " \"Security\": \"wpa\" }";
260 const char* kConfigManagedSharedConnectable =
261 "{ \"GUID\": \"wifi1\", \"Type\": \"wifi\", \"State\": \"idle\", "
262 " \"Connectable\": true, \"Security\": \"wpa\" }";
264 const char* kPolicy =
265 "[ { \"GUID\": \"wifi1\","
266 " \"Name\": \"wifi1\","
267 " \"Type\": \"WiFi\","
268 " \"WiFi\": {"
269 " \"Security\": \"WPA-PSK\","
270 " \"HexSSID\": \"7769666931\"," // "wifi1"
271 " \"Passphrase\": \"passphrase\""
272 " }"
273 "} ]";
275 const char* kPolicyCertPattern =
276 "[ { \"GUID\": \"wifi1\","
277 " \"Name\": \"wifi1\","
278 " \"Type\": \"WiFi\","
279 " \"WiFi\": {"
280 " \"Security\": \"WPA-EAP\","
281 " \"HexSSID\": \"7769666931\"," // "wifi1"
282 " \"EAP\": {"
283 " \"Outer\": \"EAP-TLS\","
284 " \"ClientCertType\": \"Pattern\","
285 " \"ClientCertPattern\": {"
286 " \"Issuer\": {"
287 " \"CommonName\": \"B CA\""
288 " }"
289 " }"
290 " }"
291 " }"
292 "} ]";
293 } // namespace
295 TEST_F(AutoConnectHandlerTest, ReconnectOnCertLoading) {
296 EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
297 EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
298 test_manager_client_->SetBestServiceToConnect("wifi1");
300 // User login shouldn't trigger any change until the certificates and policy
301 // are loaded.
302 LoginToRegularUser();
303 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
304 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
306 // Applying the policy which restricts autoconnect should disconnect from the
307 // shared, unmanaged network.
308 base::DictionaryValue global_config;
309 global_config.SetBooleanWithoutPathExpansion(
310 ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
311 true);
313 SetupPolicy(std::string(), // no network configs
314 base::DictionaryValue(), // no global config
315 true); // load as user policy
316 SetupPolicy(kPolicy, global_config, false /* load as device policy */);
317 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0"));
318 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
320 // Certificate loading should trigger connecting to the 'best' network.
321 StartCertLoader();
322 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0"));
323 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi1"));
326 TEST_F(AutoConnectHandlerTest, ReconnectOnCertPatternResolved) {
327 EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
328 EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
329 test_manager_client_->SetBestServiceToConnect("wifi0");
331 SetupPolicy(std::string(), // no device policy
332 base::DictionaryValue(), // no global config
333 false); // load as device policy
334 LoginToRegularUser();
335 StartCertLoader();
336 SetupPolicy(kPolicyCertPattern,
337 base::DictionaryValue(), // no global config
338 true); // load as user policy
340 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
341 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
343 test_manager_client_->SetBestServiceToConnect("wifi1");
344 TestCertResolveObserver observer(client_cert_resolver_.get());
346 scoped_refptr<net::X509Certificate> cert = ImportTestClientCert();
347 ASSERT_TRUE(cert.get());
349 base::RunLoop().RunUntilIdle();
350 EXPECT_TRUE(observer.DidNetworkPropertiesChange());
352 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0"));
353 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi1"));
356 // Ensure that resolving of certificate patterns only triggers a reconnect if at
357 // least one pattern was resolved.
358 TEST_F(AutoConnectHandlerTest, NoReconnectIfNoCertResolved) {
359 EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
360 EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
361 test_manager_client_->SetBestServiceToConnect("wifi0");
363 SetupPolicy(std::string(), // no device policy
364 base::DictionaryValue(), // no global config
365 false); // load as device policy
366 LoginToRegularUser();
367 StartCertLoader();
368 SetupPolicy(kPolicy,
369 base::DictionaryValue(), // no global config
370 true); // load as user policy
372 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
373 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
375 test_manager_client_->SetBestServiceToConnect("wifi1");
376 TestCertResolveObserver observer(client_cert_resolver_.get());
377 scoped_refptr<net::X509Certificate> cert = ImportTestClientCert();
378 ASSERT_TRUE(cert.get());
380 base::RunLoop().RunUntilIdle();
381 EXPECT_FALSE(observer.DidNetworkPropertiesChange());
383 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
384 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
387 TEST_F(AutoConnectHandlerTest, DisconnectOnPolicyLoading) {
388 EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
389 EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
391 // User login and certificate loading shouldn't trigger any change until the
392 // policy is loaded.
393 LoginToRegularUser();
394 StartCertLoader();
395 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
396 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
398 base::DictionaryValue global_config;
399 global_config.SetBooleanWithoutPathExpansion(
400 ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
401 true);
403 // Applying the policy which restricts autoconnect should disconnect from the
404 // shared, unmanaged network.
405 // Because no best service is set, the fake implementation of
406 // ConnectToBestServices will be a no-op.
407 SetupPolicy(kPolicy, global_config, false /* load as device policy */);
408 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0"));
409 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
412 // After login a reconnect is triggered even if there is no managed network.
413 TEST_F(AutoConnectHandlerTest, ReconnectAfterLogin) {
414 EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
415 EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
416 test_manager_client_->SetBestServiceToConnect("wifi1");
418 // User login and certificate loading shouldn't trigger any change until the
419 // policy is loaded.
420 LoginToRegularUser();
421 StartCertLoader();
422 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
423 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
425 // Applying an empty device policy will not trigger anything yet, until also
426 // the user policy is applied.
427 SetupPolicy(std::string(), // no network configs
428 base::DictionaryValue(), // no global config
429 false); // load as device policy
430 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
431 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
433 // Applying also an empty user policy should trigger connecting to the 'best'
434 // network.
435 SetupPolicy(std::string(), // no network configs
436 base::DictionaryValue(), // no global config
437 true); // load as user policy
438 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0"));
439 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi1"));
442 TEST_F(AutoConnectHandlerTest, ManualConnectAbortsReconnectAfterLogin) {
443 EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
444 EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
445 test_manager_client_->SetBestServiceToConnect("wifi1");
447 // User login and certificate loading shouldn't trigger any change until the
448 // policy is loaded.
449 LoginToRegularUser();
450 StartCertLoader();
451 SetupPolicy(std::string(), // no network configs
452 base::DictionaryValue(), // no global config
453 false); // load as device policy
455 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
456 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
458 // A manual connect request should prevent a reconnect after login.
459 auto_connect_handler_->ConnectToNetworkRequested(
460 std::string() /* service_path */);
462 // Applying the user policy after login would usually trigger connecting to
463 // the 'best' network. But the manual connect prevents this.
464 SetupPolicy(std::string(), // no network configs
465 base::DictionaryValue(), // no global config
466 true); // load as user policy
467 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
468 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
471 } // namespace chromeos