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