Upstream version 11.39.250.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / supervised_user / chromeos / manager_password_service.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 "chrome/browser/supervised_user/chromeos/manager_password_service.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/metrics/histogram.h"
10 #include "base/values.h"
11 #include "chrome/browser/chromeos/login/supervised/supervised_user_authentication.h"
12 #include "chrome/browser/chromeos/login/supervised/supervised_user_constants.h"
13 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
14 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
15 #include "chrome/browser/supervised_user/supervised_user_constants.h"
16 #include "chrome/browser/supervised_user/supervised_user_sync_service.h"
17 #include "chromeos/login/auth/key.h"
18 #include "chromeos/login/auth/user_context.h"
19 #include "components/user_manager/user.h"
20 #include "components/user_manager/user_manager.h"
21 #include "components/user_manager/user_type.h"
22
23 namespace chromeos {
24
25 ManagerPasswordService::ManagerPasswordService() : weak_ptr_factory_(this) {}
26
27 ManagerPasswordService::~ManagerPasswordService() {}
28
29 void ManagerPasswordService::Init(
30     const std::string& user_id,
31     SupervisedUserSyncService* user_service,
32     SupervisedUserSharedSettingsService* shared_settings_service) {
33   user_id_ = user_id;
34   user_service_ = user_service;
35   settings_service_ = shared_settings_service;
36   settings_service_subscription_ = settings_service_->Subscribe(
37       base::Bind(&ManagerPasswordService::OnSharedSettingsChange,
38                  weak_ptr_factory_.GetWeakPtr()));
39
40   authenticator_ = ExtendedAuthenticator::Create(this);
41
42   SupervisedUserManager* supervised_user_manager =
43       ChromeUserManager::Get()->GetSupervisedUserManager();
44
45   const user_manager::UserList& users =
46       user_manager::UserManager::Get()->GetUsers();
47
48   for (user_manager::UserList::const_iterator it = users.begin();
49        it != users.end();
50        ++it) {
51     if ((*it)->GetType() != user_manager::USER_TYPE_SUPERVISED)
52       continue;
53     if (user_id != supervised_user_manager->GetManagerUserId((*it)->email()))
54       continue;
55     OnSharedSettingsChange(
56         supervised_user_manager->GetUserSyncId((*it)->email()),
57         supervised_users::kChromeOSPasswordData);
58   }
59 }
60
61 void ManagerPasswordService::OnSharedSettingsChange(
62     const std::string& su_id,
63     const std::string& key) {
64   if (key != supervised_users::kChromeOSPasswordData)
65     return;
66
67   SupervisedUserManager* supervised_user_manager =
68       ChromeUserManager::Get()->GetSupervisedUserManager();
69   const user_manager::User* user = supervised_user_manager->FindBySyncId(su_id);
70   // No user on device.
71   if (user == NULL)
72     return;
73
74   const base::Value* value = settings_service_->GetValue(su_id, key);
75
76   if (value == NULL) {
77     LOG(WARNING) << "Got empty value from sync.";
78     return;
79   }
80   const base::DictionaryValue* dict;
81   if (!value->GetAsDictionary(&dict)) {
82     LOG(WARNING) << "Got non-dictionary value from sync.";
83     return;
84   }
85
86   SupervisedUserAuthentication* auth =
87       supervised_user_manager->GetAuthentication();
88
89   if (!auth->NeedPasswordChange(user->email(), dict) &&
90       !auth->HasIncompleteKey(user->email())) {
91     return;
92   }
93   scoped_ptr<base::DictionaryValue> wrapper(dict->DeepCopy());
94   user_service_->GetSupervisedUsersAsync(
95       base::Bind(&ManagerPasswordService::GetSupervisedUsersCallback,
96                  weak_ptr_factory_.GetWeakPtr(),
97                  su_id,
98                  user->email(),
99                  Passed(&wrapper)));
100 }
101
102 void ManagerPasswordService::GetSupervisedUsersCallback(
103     const std::string& sync_su_id,
104     const std::string& user_id,
105     scoped_ptr<base::DictionaryValue> password_data,
106     const base::DictionaryValue* supervised_users) {
107   const base::DictionaryValue* supervised_user = NULL;
108   if (!supervised_users->GetDictionary(sync_su_id, &supervised_user))
109     return;
110   std::string master_key;
111   std::string encryption_key;
112   std::string signature_key;
113   if (!supervised_user->GetString(SupervisedUserSyncService::kMasterKey,
114                                   &master_key)) {
115     LOG(WARNING) << "Can not apply password change to " << user_id
116                  << ": no master key found";
117     UMA_HISTOGRAM_ENUMERATION(
118         "ManagedUsers.ChromeOS.PasswordChange",
119         SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_NO_MASTER_KEY,
120         SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
121     return;
122   }
123
124   if (!supervised_user->GetString(
125           SupervisedUserSyncService::kPasswordSignatureKey, &signature_key) ||
126       !supervised_user->GetString(
127           SupervisedUserSyncService::kPasswordEncryptionKey,
128           &encryption_key)) {
129     LOG(WARNING) << "Can not apply password change to " << user_id
130                  << ": no signature / encryption keys.";
131     UMA_HISTOGRAM_ENUMERATION(
132         "ManagedUsers.ChromeOS.PasswordChange",
133         SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_NO_SIGNATURE_KEY,
134         SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
135     return;
136   }
137
138   UserContext manager_key(user_id);
139   manager_key.SetKey(Key(master_key));
140   manager_key.SetIsUsingOAuth(false);
141
142   // As master key can have old label, leave label field empty - it will work
143   // as wildcard.
144
145   std::string new_key;
146   int revision;
147
148   bool has_data = password_data->GetStringWithoutPathExpansion(
149       kEncryptedPassword, &new_key);
150   has_data &= password_data->GetIntegerWithoutPathExpansion(kPasswordRevision,
151                                                             &revision);
152   if (!has_data) {
153     LOG(WARNING) << "Can not apply password change to " << user_id
154                  << ": incomplete password data.";
155     UMA_HISTOGRAM_ENUMERATION(
156         "ManagedUsers.ChromeOS.PasswordChange",
157         SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_NO_PASSWORD_DATA,
158         SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
159     return;
160   }
161
162   cryptohome::KeyDefinition new_key_definition(
163       new_key,
164       kCryptohomeSupervisedUserKeyLabel,
165       cryptohome::PRIV_AUTHORIZED_UPDATE || cryptohome::PRIV_MOUNT);
166   new_key_definition.revision = revision;
167   new_key_definition.authorization_data.push_back(
168       cryptohome::KeyDefinition::AuthorizationData(true /* encrypt */,
169                                                    false /* sign */,
170                                                    encryption_key));
171   new_key_definition.authorization_data.push_back(
172       cryptohome::KeyDefinition::AuthorizationData(false /* encrypt */,
173                                                    true /* sign */,
174                                                    signature_key));
175
176   authenticator_->AddKey(manager_key,
177                          new_key_definition,
178                          true /* replace existing */,
179                          base::Bind(&ManagerPasswordService::OnAddKeySuccess,
180                                     weak_ptr_factory_.GetWeakPtr(),
181                                     manager_key,
182                                     user_id,
183                                     Passed(&password_data)));
184 }
185
186 void ManagerPasswordService::OnAuthenticationFailure(
187     ExtendedAuthenticator::AuthState state) {
188   UMA_HISTOGRAM_ENUMERATION(
189       "ManagedUsers.ChromeOS.PasswordChange",
190       SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_MASTER_KEY_FAILURE,
191       SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
192   LOG(ERROR) << "Can not apply password change, master key failure";
193 }
194
195 void ManagerPasswordService::OnAddKeySuccess(
196     const UserContext& master_key_context,
197     const std::string& user_id,
198     scoped_ptr<base::DictionaryValue> password_data) {
199   VLOG(0) << "Password changed for " << user_id;
200   UMA_HISTOGRAM_ENUMERATION(
201       "ManagedUsers.ChromeOS.PasswordChange",
202       SupervisedUserAuthentication::PASSWORD_CHANGED_IN_MANAGER_SESSION,
203       SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
204
205   SupervisedUserAuthentication* auth =
206       ChromeUserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
207   int old_schema = auth->GetPasswordSchema(user_id);
208   auth->StorePasswordData(user_id, *password_data.get());
209
210   if (auth->HasIncompleteKey(user_id))
211     auth->MarkKeyIncomplete(user_id, false /* key is complete now */);
212
213   // Check if we have legacy labels for keys.
214   // TODO(antrim): Migrate it to GetLabels call once wad@ implement it.
215   if (old_schema == SupervisedUserAuthentication::SCHEMA_PLAIN) {
216     // 1) Add new manager key (using old key).
217     // 2) Remove old supervised user key.
218     // 3) Remove old manager key.
219     authenticator_->TransformKeyIfNeeded(
220         master_key_context,
221         base::Bind(&ManagerPasswordService::OnKeyTransformedIfNeeded,
222                    weak_ptr_factory_.GetWeakPtr()));
223   }
224 }
225
226 void ManagerPasswordService::OnKeyTransformedIfNeeded(
227     const UserContext& master_key_context) {
228   const Key* const key = master_key_context.GetKey();
229   DCHECK_NE(Key::KEY_TYPE_PASSWORD_PLAIN, key->GetKeyType());
230   cryptohome::KeyDefinition new_master_key(key->GetSecret(),
231                                            kCryptohomeMasterKeyLabel,
232                                            cryptohome::PRIV_DEFAULT);
233   // Use new master key for further actions.
234   UserContext new_master_key_context = master_key_context;
235   new_master_key_context.GetKey()->SetLabel(kCryptohomeMasterKeyLabel);
236   authenticator_->AddKey(
237       master_key_context,
238       new_master_key,
239       true /* replace existing */,
240       base::Bind(&ManagerPasswordService::OnNewManagerKeySuccess,
241                  weak_ptr_factory_.GetWeakPtr(),
242                  new_master_key_context));
243 }
244
245 void ManagerPasswordService::OnNewManagerKeySuccess(
246     const UserContext& master_key_context) {
247   VLOG(1) << "Added new master key for " << master_key_context.GetUserID();
248   authenticator_->RemoveKey(
249       master_key_context,
250       kLegacyCryptohomeSupervisedUserKeyLabel,
251       base::Bind(&ManagerPasswordService::OnOldSupervisedUserKeyDeleted,
252                  weak_ptr_factory_.GetWeakPtr(),
253                  master_key_context));
254 }
255
256 void ManagerPasswordService::OnOldSupervisedUserKeyDeleted(
257     const UserContext& master_key_context) {
258   VLOG(1) << "Removed old supervised user key for "
259           << master_key_context.GetUserID();
260   authenticator_->RemoveKey(
261       master_key_context,
262       kLegacyCryptohomeMasterKeyLabel,
263       base::Bind(&ManagerPasswordService::OnOldManagerKeyDeleted,
264                  weak_ptr_factory_.GetWeakPtr(),
265                  master_key_context));
266 }
267
268 void ManagerPasswordService::OnOldManagerKeyDeleted(
269     const UserContext& master_key_context) {
270   VLOG(1) << "Removed old master key for " << master_key_context.GetUserID();
271 }
272
273 void ManagerPasswordService::Shutdown() {
274   settings_service_subscription_.reset();
275 }
276
277 }  // namespace chromeos