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 <string>
6
7#include "base/compiler_specific.h"
8#include "base/run_loop.h"
9#include "base/strings/utf_string_conversions.h"
10#include "base/threading/sequenced_worker_pool.h"
11#include "chrome/browser/chrome_notification_types.h"
12#include "chrome/browser/chromeos/login/login_manager_test.h"
13#include "chrome/browser/chromeos/login/startup_utils.h"
14#include "chrome/browser/chromeos/login/supervised/supervised_user_authentication.h"
15#include "chrome/browser/chromeos/login/supervised/supervised_user_test_base.h"
16#include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
17#include "chrome/browser/chromeos/login/ui/webui_login_view.h"
18#include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
19#include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
20#include "chrome/browser/chromeos/net/network_portal_detector_test_impl.h"
21#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
22#include "chrome/browser/supervised_user/supervised_user_constants.h"
23#include "chrome/browser/supervised_user/supervised_user_registration_utility.h"
24#include "chrome/browser/supervised_user/supervised_user_registration_utility_stub.h"
25#include "chrome/browser/supervised_user/supervised_user_shared_settings_service.h"
26#include "chrome/browser/supervised_user/supervised_user_shared_settings_service_factory.h"
27#include "chrome/browser/supervised_user/supervised_user_sync_service.h"
28#include "chrome/browser/supervised_user/supervised_user_sync_service_factory.h"
29#include "chromeos/cryptohome/mock_async_method_caller.h"
30#include "chromeos/cryptohome/mock_homedir_methods.h"
31#include "content/public/browser/notification_service.h"
32#include "content/public/test/browser_test_utils.h"
33#include "content/public/test/test_utils.h"
34#include "sync/api/fake_sync_change_processor.h"
35#include "sync/api/sync_change.h"
36#include "sync/api/sync_error_factory_mock.h"
37#include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h"
38#include "sync/protocol/sync.pb.h"
39
40using testing::_;
41using chromeos::SupervisedUserTestBase;
42using chromeos::kTestSupervisedUserDisplayName;
43using chromeos::kTestManager;
44
45namespace chromeos {
46
47class SupervisedUserPasswordTest : public SupervisedUserTestBase {
48 public:
49  SupervisedUserPasswordTest() : SupervisedUserTestBase() {}
50
51 private:
52  DISALLOW_COPY_AND_ASSIGN(SupervisedUserPasswordTest);
53};
54
55class SupervisedUserPasswordManagerTest : public SupervisedUserTestBase {
56 public:
57  SupervisedUserPasswordManagerTest() : SupervisedUserTestBase() {}
58
59 private:
60  DISALLOW_COPY_AND_ASSIGN(SupervisedUserPasswordManagerTest);
61};
62
63IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest,
64                       DISABLED_PRE_PRE_PRE_PasswordChangeFromUserTest) {
65  PrepareUsers();
66}
67
68IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest,
69                       DISABLED_PRE_PRE_PasswordChangeFromUserTest) {
70  StartFlowLoginAsManager();
71  FillNewUserData(kTestSupervisedUserDisplayName);
72  StartUserCreation("supervised-user-creation-next-button",
73                    kTestSupervisedUserDisplayName);
74}
75
76// Supervised user signs in, get sync notification about password update, and
77// schedules password migration.
78IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest,
79                       DISABLED_PRE_PasswordChangeFromUserTest) {
80  SigninAsSupervisedUser(true, 0, kTestSupervisedUserDisplayName);
81
82  const user_manager::User* user =
83      user_manager::UserManager::Get()->GetUsers().at(0);
84  std::string sync_id =
85      ChromeUserManager::Get()->GetSupervisedUserManager()->GetUserSyncId(
86          user->email());
87  base::DictionaryValue password;
88  password.SetIntegerWithoutPathExpansion(
89      kSchemaVersion, SupervisedUserAuthentication::SCHEMA_SALT_HASHED);
90  password.SetIntegerWithoutPathExpansion(kPasswordRevision, 2);
91
92  password.SetStringWithoutPathExpansion(kPasswordSignature, "signature");
93  password.SetStringWithoutPathExpansion(kEncryptedPassword,
94                                         "new-encrypted-password");
95
96  shared_settings_adapter_->AddChange(
97      sync_id, supervised_users::kChromeOSPasswordData, password, true, false);
98  content::RunAllPendingInMessageLoop();
99}
100
101// Supervised user signs in for second time, and actual password migration takes
102// place.
103IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest,
104                       DISABLED_PasswordChangeFromUserTest) {
105  EXPECT_CALL(*mock_homedir_methods_, MountEx(_, _, _, _)).Times(1);
106  EXPECT_CALL(*mock_homedir_methods_, UpdateKeyEx(_, _, _, _, _)).Times(1);
107  SigninAsSupervisedUser(false, 0, kTestSupervisedUserDisplayName);
108  testing::Mock::VerifyAndClearExpectations(mock_homedir_methods_);
109}
110
111IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest,
112                       DISABLED_PRE_PRE_PRE_PasswordChangeFromManagerTest) {
113  PrepareUsers();
114}
115
116IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest,
117                       DISABLED_PRE_PRE_PasswordChangeFromManagerTest) {
118  StartFlowLoginAsManager();
119  FillNewUserData(kTestSupervisedUserDisplayName);
120  StartUserCreation("supervised-user-creation-next-button",
121                    kTestSupervisedUserDisplayName);
122}
123
124// Manager signs in, gets sync notification about supervised user password
125// update, and performs migration.
126IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest,
127                       DISABLED_PRE_PasswordChangeFromManagerTest) {
128  const user_manager::User* supervised_user =
129      user_manager::UserManager::Get()->GetUsers().at(0);
130
131  SigninAsManager(1);
132
133  EXPECT_CALL(*mock_homedir_methods_, AddKeyEx(_, _, _, _, _)).Times(1);
134
135  std::string sync_id =
136      ChromeUserManager::Get()->GetSupervisedUserManager()->GetUserSyncId(
137          supervised_user->email());
138
139  ::sync_pb::ManagedUserSpecifics managed_user_proto;
140
141  managed_user_proto.set_id(sync_id);
142  managed_user_proto.set_name(kTestSupervisedUserDisplayName);
143  managed_user_proto.set_acknowledged(true);
144  managed_user_proto.set_master_key("master key");
145  managed_user_proto.set_password_signature_key("signature_key");
146  managed_user_proto.set_password_encryption_key("encryption_key");
147
148  supervised_users_adapter_->AddChange(managed_user_proto, false);
149  content::RunAllPendingInMessageLoop();
150
151  base::DictionaryValue password;
152  password.SetIntegerWithoutPathExpansion(
153      kSchemaVersion, SupervisedUserAuthentication::SCHEMA_SALT_HASHED);
154  password.SetIntegerWithoutPathExpansion(kPasswordRevision, 2);
155
156  password.SetStringWithoutPathExpansion(kPasswordSignature, "signature");
157  password.SetStringWithoutPathExpansion(kEncryptedPassword,
158                                         "new-encrypted-password");
159  shared_settings_adapter_->AddChange(
160      sync_id, supervised_users::kChromeOSPasswordData, password, true, false);
161  content::RunAllPendingInMessageLoop();
162
163  testing::Mock::VerifyAndClearExpectations(mock_homedir_methods_);
164}
165
166// After that supervised user signs in, and no password change happens.
167IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest,
168                       DISABLED_PasswordChangeFromManagerTest) {
169  EXPECT_CALL(*mock_homedir_methods_, MountEx(_, _, _, _)).Times(1);
170  EXPECT_CALL(*mock_homedir_methods_, UpdateKeyEx(_, _, _, _, _)).Times(0);
171  SigninAsSupervisedUser(false, 1, kTestSupervisedUserDisplayName);
172  testing::Mock::VerifyAndClearExpectations(mock_homedir_methods_);
173}
174
175IN_PROC_BROWSER_TEST_F(
176    SupervisedUserPasswordTest,
177    DISABLED_PRE_PRE_PRE_PRE_PasswordChangeUserAndManagerTest) {
178  PrepareUsers();
179}
180
181IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest,
182                       DISABLED_PRE_PRE_PRE_PasswordChangeUserAndManagerTest) {
183  StartFlowLoginAsManager();
184  FillNewUserData(kTestSupervisedUserDisplayName);
185  StartUserCreation("supervised-user-creation-next-button",
186                    kTestSupervisedUserDisplayName);
187}
188
189// Supervised user signs in, get sync notification about password update, and
190// schedules password migration.
191IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest,
192                       DISABLED_PRE_PRE_PasswordChangeUserAndManagerTest) {
193  SigninAsSupervisedUser(true, 0, kTestSupervisedUserDisplayName);
194
195  const user_manager::User* user =
196      user_manager::UserManager::Get()->GetUsers().at(0);
197  std::string sync_id =
198      ChromeUserManager::Get()->GetSupervisedUserManager()->GetUserSyncId(
199          user->email());
200  base::DictionaryValue password;
201  password.SetIntegerWithoutPathExpansion(
202      kSchemaVersion, SupervisedUserAuthentication::SCHEMA_SALT_HASHED);
203  password.SetIntegerWithoutPathExpansion(kPasswordRevision, 2);
204
205  password.SetStringWithoutPathExpansion(kPasswordSignature, "signature");
206  password.SetStringWithoutPathExpansion(kEncryptedPassword,
207                                         "new-encrypted-password");
208
209  shared_settings_adapter_->AddChange(
210      sync_id, supervised_users::kChromeOSPasswordData, password, true, false);
211  content::RunAllPendingInMessageLoop();
212}
213
214// After that manager signs in, and also detects password change. Manager
215// performs the migration.
216IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest,
217                       DISABLED_PRE_PasswordChangeUserAndManagerTest) {
218  const user_manager::User* supervised_user =
219      user_manager::UserManager::Get()->GetUsers().at(0);
220
221  SigninAsManager(1);
222
223  EXPECT_CALL(*mock_homedir_methods_, AddKeyEx(_, _, _, _, _)).Times(1);
224
225  std::string sync_id =
226      ChromeUserManager::Get()->GetSupervisedUserManager()->GetUserSyncId(
227          supervised_user->email());
228
229  ::sync_pb::ManagedUserSpecifics managed_user_proto;
230
231  managed_user_proto.set_id(sync_id);
232  managed_user_proto.set_name(kTestSupervisedUserDisplayName);
233  managed_user_proto.set_acknowledged(true);
234  managed_user_proto.set_master_key("master key");
235  managed_user_proto.set_password_signature_key("signature_key");
236  managed_user_proto.set_password_encryption_key("encryption_key");
237
238  supervised_users_adapter_->AddChange(managed_user_proto, false);
239  content::RunAllPendingInMessageLoop();
240
241  base::DictionaryValue password;
242  password.SetIntegerWithoutPathExpansion(
243      kSchemaVersion, SupervisedUserAuthentication::SCHEMA_SALT_HASHED);
244  password.SetIntegerWithoutPathExpansion(kPasswordRevision, 2);
245
246  password.SetStringWithoutPathExpansion(kPasswordSignature, "signature");
247  password.SetStringWithoutPathExpansion(kEncryptedPassword,
248                                         "new-encrypted-password");
249  shared_settings_adapter_->AddChange(
250      sync_id, supervised_users::kChromeOSPasswordData, password, true, false);
251  content::RunAllPendingInMessageLoop();
252
253  testing::Mock::VerifyAndClearExpectations(mock_homedir_methods_);
254}
255
256// When supervised user signs in, password is already migrated, so no migration
257// should be attempted.
258IN_PROC_BROWSER_TEST_F(SupervisedUserPasswordTest,
259                       DISABLED_PasswordChangeUserAndManagerTest) {
260  EXPECT_CALL(*mock_homedir_methods_, MountEx(_, _, _, _)).Times(1);
261  EXPECT_CALL(*mock_homedir_methods_, UpdateKeyEx(_, _, _, _, _)).Times(0);
262  SigninAsSupervisedUser(false, 1, kTestSupervisedUserDisplayName);
263  testing::Mock::VerifyAndClearExpectations(mock_homedir_methods_);
264}
265
266}  // namespace chromeos
267