Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / chromeos / network / auto_connect_handler_unittest.cc
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.
4
5 #include "chromeos/network/auto_connect_handler.h"
6
7 #include <string>
8
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"
39
40 // http://crbug.com/418369
41 #ifdef NDEBUG
42
43 namespace chromeos {
44
45 namespace {
46
47 const char* kUserHash = "user_hash";
48
49 void ConfigureCallback(const dbus::ObjectPath& result) {
50 }
51
52 void FailErrorCallback(const std::string& error_name,
53                             const std::string& error_message) {
54   // This function is not expected to be called.
55   EXPECT_TRUE(false);
56 }
57
58 class TestCertResolveObserver : public ClientCertResolver::Observer {
59  public:
60   explicit TestCertResolveObserver(ClientCertResolver* cert_resolver)
61       : changed_network_properties_(false), cert_resolver_(cert_resolver) {
62     cert_resolver_->AddObserver(this);
63   }
64
65   void ResolveRequestCompleted(bool changed_network_properties) override {
66     cert_resolver_->RemoveObserver(this);
67     changed_network_properties_ = changed_network_properties;
68   }
69
70   bool DidNetworkPropertiesChange() { return changed_network_properties_; }
71
72  private:
73   bool changed_network_properties_;
74   ClientCertResolver* cert_resolver_;
75 };
76
77 }  // namespace
78
79 class AutoConnectHandlerTest : public testing::Test {
80  public:
81   AutoConnectHandlerTest()
82       : test_manager_client_(nullptr), test_service_client_(nullptr) {}
83
84   void SetUp() override {
85     ASSERT_TRUE(test_nssdb_.is_open());
86
87     // Use the same DB for public and private slot.
88     test_nsscertdb_.reset(new net::NSSCertDatabaseChromeOS(
89         crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot())),
90         crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot()))));
91     test_nsscertdb_->SetSlowTaskRunnerForTest(message_loop_.task_runner());
92
93     CertLoader::Initialize();
94     CertLoader::ForceHardwareBackedForTesting();
95
96     DBusThreadManager::Initialize();
97     DBusThreadManager* dbus_manager = DBusThreadManager::Get();
98     test_manager_client_ =
99         dbus_manager->GetShillManagerClient()->GetTestInterface();
100     test_service_client_ =
101         dbus_manager->GetShillServiceClient()->GetTestInterface();
102
103     test_manager_client_->AddTechnology(shill::kTypeWifi, true /* enabled */);
104     dbus_manager->GetShillDeviceClient()->GetTestInterface()->AddDevice(
105         "/device/wifi1", shill::kTypeWifi, "wifi_device1");
106     test_manager_client_->AddTechnology(shill::kTypeCellular,
107                                         true /* enabled */);
108     dbus_manager->GetShillProfileClient()->GetTestInterface()->AddProfile(
109         "shared_profile_path", std::string() /* shared profile */);
110     dbus_manager->GetShillProfileClient()->GetTestInterface()->AddProfile(
111         "user_profile_path", kUserHash);
112
113     base::RunLoop().RunUntilIdle();
114     LoginState::Initialize();
115     network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
116     network_config_handler_.reset(
117         NetworkConfigurationHandler::InitializeForTest(
118             network_state_handler_.get()));
119
120     network_profile_handler_.reset(new NetworkProfileHandler());
121     network_profile_handler_->Init();
122
123     managed_config_handler_.reset(new ManagedNetworkConfigurationHandlerImpl());
124     managed_config_handler_->Init(
125         network_state_handler_.get(), network_profile_handler_.get(),
126         network_config_handler_.get(), nullptr /* network_device_handler */);
127
128     client_cert_resolver_.reset(new ClientCertResolver());
129     client_cert_resolver_->Init(network_state_handler_.get(),
130                                 managed_config_handler_.get());
131     client_cert_resolver_->SetSlowTaskRunnerForTest(
132         message_loop_.task_runner());
133
134     auto_connect_handler_.reset(new AutoConnectHandler());
135     auto_connect_handler_->Init(client_cert_resolver_.get(),
136                                 nullptr,  // no connection handler
137                                 network_state_handler_.get(),
138                                 managed_config_handler_.get());
139
140     base::RunLoop().RunUntilIdle();
141   }
142
143   void TearDown() override {
144     auto_connect_handler_.reset();
145     client_cert_resolver_.reset();
146     managed_config_handler_.reset();
147     network_profile_handler_.reset();
148     network_config_handler_.reset();
149     network_state_handler_.reset();
150     CertLoader::Shutdown();
151     LoginState::Shutdown();
152     DBusThreadManager::Shutdown();
153   }
154
155  protected:
156   bool Configure(const std::string& json_string) {
157     scoped_ptr<base::DictionaryValue> json_dict =
158         onc::ReadDictionaryFromJson(json_string);
159     if (!json_dict) {
160       LOG(ERROR) << "Error parsing json: " << json_string;
161       return false;
162     }
163     DBusThreadManager::Get()->GetShillManagerClient()->ConfigureService(
164         *json_dict, base::Bind(&ConfigureCallback),
165         base::Bind(&FailErrorCallback));
166     base::RunLoop().RunUntilIdle();
167     return true;
168   }
169
170   std::string GetServiceState(const std::string& service_path) {
171     const base::DictionaryValue* properties =
172         test_service_client_->GetServiceProperties(service_path);
173     std::string result;
174     if (properties)
175       properties->GetStringWithoutPathExpansion(shill::kStateProperty, &result);
176     return result;
177   }
178
179   void StartCertLoader() {
180     CertLoader::Get()->StartWithNSSDB(test_nsscertdb_.get());
181     base::RunLoop().RunUntilIdle();
182   }
183
184   void LoginToRegularUser() {
185     LoginState::Get()->SetLoggedInState(LoginState::LOGGED_IN_ACTIVE,
186                                         LoginState::LOGGED_IN_USER_REGULAR);
187     base::RunLoop().RunUntilIdle();
188   }
189
190   scoped_refptr<net::X509Certificate> ImportTestClientCert() {
191     net::CertificateList ca_cert_list = net::CreateCertificateListFromFile(
192         net::GetTestCertsDirectory(), "client_1_ca.pem",
193         net::X509Certificate::FORMAT_AUTO);
194     if (ca_cert_list.empty()) {
195       LOG(ERROR) << "No CA cert loaded.";
196       return nullptr;
197     }
198     net::NSSCertDatabase::ImportCertFailureList failures;
199     EXPECT_TRUE(test_nsscertdb_->ImportCACerts(
200         ca_cert_list, net::NSSCertDatabase::TRUST_DEFAULT, &failures));
201     if (!failures.empty()) {
202       LOG(ERROR) << net::ErrorToString(failures[0].net_error);
203       return nullptr;
204     }
205
206     // Import a client cert signed by that CA.
207     scoped_refptr<net::X509Certificate> client_cert(
208         net::ImportClientCertAndKeyFromFile(net::GetTestCertsDirectory(),
209                                             "client_1.pem", "client_1.pk8",
210                                             test_nssdb_.slot()));
211     return client_cert;
212   }
213
214   void SetupPolicy(const std::string& network_configs_json,
215                    const base::DictionaryValue& global_config,
216                    bool user_policy) {
217     scoped_ptr<base::ListValue> network_configs(new base::ListValue);
218     if (!network_configs_json.empty()) {
219       std::string error;
220       base::Value* network_configs_value = base::JSONReader::ReadAndReturnError(
221           network_configs_json, base::JSON_ALLOW_TRAILING_COMMAS, nullptr,
222           &error);
223       ASSERT_TRUE(network_configs_value) << error;
224       base::ListValue* network_configs_list = nullptr;
225       ASSERT_TRUE(network_configs_value->GetAsList(&network_configs_list));
226       network_configs.reset(network_configs_list);
227     }
228
229     if (user_policy) {
230       managed_config_handler_->SetPolicy(::onc::ONC_SOURCE_USER_POLICY,
231                                          kUserHash, *network_configs,
232                                          global_config);
233     } else {
234       managed_config_handler_->SetPolicy(::onc::ONC_SOURCE_DEVICE_POLICY,
235                                          std::string(),  // no username hash
236                                          *network_configs, global_config);
237     }
238     base::RunLoop().RunUntilIdle();
239   }
240
241   scoped_ptr<AutoConnectHandler> auto_connect_handler_;
242   scoped_ptr<ClientCertResolver> client_cert_resolver_;
243   scoped_ptr<NetworkStateHandler> network_state_handler_;
244   scoped_ptr<NetworkConfigurationHandler> network_config_handler_;
245   scoped_ptr<ManagedNetworkConfigurationHandlerImpl> managed_config_handler_;
246   scoped_ptr<NetworkProfileHandler> network_profile_handler_;
247   ShillManagerClient::TestInterface* test_manager_client_;
248   ShillServiceClient::TestInterface* test_service_client_;
249   crypto::ScopedTestNSSDB test_nssdb_;
250   scoped_ptr<net::NSSCertDatabaseChromeOS> test_nsscertdb_;
251   base::MessageLoopForUI message_loop_;
252
253  private:
254   DISALLOW_COPY_AND_ASSIGN(AutoConnectHandlerTest);
255 };
256
257 namespace {
258
259 const char* kConfigUnmanagedSharedConnected =
260     "{ \"GUID\": \"wifi0\", \"Type\": \"wifi\", \"State\": \"online\", "
261     "  \"Security\": \"wpa\" }";
262 const char* kConfigManagedSharedConnectable =
263     "{ \"GUID\": \"wifi1\", \"Type\": \"wifi\", \"State\": \"idle\", "
264     "  \"Connectable\": true, \"Security\": \"wpa\" }";
265
266 const char* kPolicy =
267     "[ { \"GUID\": \"wifi1\","
268     "    \"Name\": \"wifi1\","
269     "    \"Type\": \"WiFi\","
270     "    \"WiFi\": {"
271     "      \"Security\": \"WPA-PSK\","
272     "      \"SSID\": \"wifi1\","
273     "      \"Passphrase\": \"passphrase\""
274     "    }"
275     "} ]";
276
277 const char* kPolicyCertPattern =
278     "[ { \"GUID\": \"wifi1\","
279     "    \"Name\": \"wifi1\","
280     "    \"Type\": \"WiFi\","
281     "    \"WiFi\": {"
282     "      \"Security\": \"WPA-EAP\","
283     "      \"SSID\": \"wifi1\","
284     "      \"EAP\": {"
285     "        \"Outer\": \"EAP-TLS\","
286     "        \"ClientCertType\": \"Pattern\","
287     "        \"ClientCertPattern\": {"
288     "          \"Issuer\": {"
289     "            \"CommonName\": \"B CA\""
290     "          }"
291     "        }"
292     "      }"
293     "    }"
294     "} ]";
295 }  // namespace
296
297 TEST_F(AutoConnectHandlerTest, ReconnectOnCertLoading) {
298   EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
299   EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
300   test_manager_client_->SetBestServiceToConnect("wifi1");
301
302   // User login shouldn't trigger any change until the certificates and policy
303   // are loaded.
304   LoginToRegularUser();
305   EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
306   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
307
308   // Applying the policy which restricts autoconnect should disconnect from the
309   // shared, unmanaged network.
310   base::DictionaryValue global_config;
311   global_config.SetBooleanWithoutPathExpansion(
312       ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
313       true);
314
315   SetupPolicy(std::string(),            // no network configs
316               base::DictionaryValue(),  // no global config
317               true);                    // load as user policy
318   SetupPolicy(kPolicy, global_config, false /* load as device policy */);
319   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0"));
320   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
321
322   // Certificate loading should trigger connecting to the 'best' network.
323   StartCertLoader();
324   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0"));
325   EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi1"));
326 }
327
328 TEST_F(AutoConnectHandlerTest, ReconnectOnCertPatternResolved) {
329   EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
330   EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
331   test_manager_client_->SetBestServiceToConnect("wifi0");
332
333   SetupPolicy(std::string(),            // no device policy
334               base::DictionaryValue(),  // no global config
335               false);                   // load as device policy
336   LoginToRegularUser();
337   StartCertLoader();
338   SetupPolicy(kPolicyCertPattern,
339               base::DictionaryValue(),  // no global config
340               true);                    // load as user policy
341
342   EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
343   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
344
345   test_manager_client_->SetBestServiceToConnect("wifi1");
346   TestCertResolveObserver observer(client_cert_resolver_.get());
347
348   scoped_refptr<net::X509Certificate> cert = ImportTestClientCert();
349   ASSERT_TRUE(cert.get());
350
351   base::RunLoop().RunUntilIdle();
352   EXPECT_TRUE(observer.DidNetworkPropertiesChange());
353
354   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0"));
355   EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi1"));
356 }
357
358 // Ensure that resolving of certificate patterns only triggers a reconnect if at
359 // least one pattern was resolved.
360 TEST_F(AutoConnectHandlerTest, NoReconnectIfNoCertResolved) {
361   EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
362   EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
363   test_manager_client_->SetBestServiceToConnect("wifi0");
364
365   SetupPolicy(std::string(),            // no device policy
366               base::DictionaryValue(),  // no global config
367               false);                   // load as device policy
368   LoginToRegularUser();
369   StartCertLoader();
370   SetupPolicy(kPolicy,
371               base::DictionaryValue(),  // no global config
372               true);                    // load as user policy
373
374   EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
375   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
376
377   test_manager_client_->SetBestServiceToConnect("wifi1");
378   TestCertResolveObserver observer(client_cert_resolver_.get());
379   scoped_refptr<net::X509Certificate> cert = ImportTestClientCert();
380   ASSERT_TRUE(cert.get());
381
382   base::RunLoop().RunUntilIdle();
383   EXPECT_FALSE(observer.DidNetworkPropertiesChange());
384
385   EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
386   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
387 }
388
389 TEST_F(AutoConnectHandlerTest, DisconnectOnPolicyLoading) {
390   EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
391   EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
392
393   // User login and certificate loading shouldn't trigger any change until the
394   // policy is loaded.
395   LoginToRegularUser();
396   StartCertLoader();
397   EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
398   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
399
400   base::DictionaryValue global_config;
401   global_config.SetBooleanWithoutPathExpansion(
402       ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
403       true);
404
405   // Applying the policy which restricts autoconnect should disconnect from the
406   // shared, unmanaged network.
407   // Because no best service is set, the fake implementation of
408   // ConnectToBestServices will be a no-op.
409   SetupPolicy(kPolicy, global_config, false /* load as device policy */);
410   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0"));
411   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
412 }
413
414 // After login a reconnect is triggered even if there is no managed network.
415 TEST_F(AutoConnectHandlerTest, ReconnectAfterLogin) {
416   EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
417   EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
418   test_manager_client_->SetBestServiceToConnect("wifi1");
419
420   // User login and certificate loading shouldn't trigger any change until the
421   // policy is loaded.
422   LoginToRegularUser();
423   StartCertLoader();
424   EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
425   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
426
427   // Applying an empty device policy will not trigger anything yet, until also
428   // the user policy is applied.
429   SetupPolicy(std::string(),            // no network configs
430               base::DictionaryValue(),  // no global config
431               false);                   // load as device policy
432   EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
433   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
434
435   // Applying also an empty user policy should trigger connecting to the 'best'
436   // network.
437   SetupPolicy(std::string(),            // no network configs
438               base::DictionaryValue(),  // no global config
439               true);                    // load as user policy
440   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0"));
441   EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi1"));
442 }
443
444 TEST_F(AutoConnectHandlerTest, ManualConnectAbortsReconnectAfterLogin) {
445   EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
446   EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
447   test_manager_client_->SetBestServiceToConnect("wifi1");
448
449   // User login and certificate loading shouldn't trigger any change until the
450   // policy is loaded.
451   LoginToRegularUser();
452   StartCertLoader();
453   SetupPolicy(std::string(),            // no network configs
454               base::DictionaryValue(),  // no global config
455               false);                   // load as device policy
456
457   EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
458   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
459
460   // A manual connect request should prevent a reconnect after login.
461   auto_connect_handler_->ConnectToNetworkRequested(
462       std::string() /* service_path */);
463
464   // Applying the user policy after login would usually trigger connecting to
465   // the 'best' network. But the manual connect prevents this.
466   SetupPolicy(std::string(),            // no network configs
467               base::DictionaryValue(),  // no global config
468               true);                    // load as user policy
469   EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0"));
470   EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1"));
471 }
472
473 }  // namespace chromeos
474
475 #endif