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 "chrome/browser/supervised_user/chromeos/manager_password_service.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"
25 ManagerPasswordService::ManagerPasswordService() : weak_ptr_factory_(this) {}
27 ManagerPasswordService::~ManagerPasswordService() {}
29 void ManagerPasswordService::Init(
30 const std::string& user_id,
31 SupervisedUserSyncService* user_service,
32 SupervisedUserSharedSettingsService* shared_settings_service) {
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()));
40 authenticator_ = ExtendedAuthenticator::Create(this);
42 SupervisedUserManager* supervised_user_manager =
43 ChromeUserManager::Get()->GetSupervisedUserManager();
45 const user_manager::UserList& users =
46 user_manager::UserManager::Get()->GetUsers();
48 for (user_manager::UserList::const_iterator it = users.begin();
51 if ((*it)->GetType() != user_manager::USER_TYPE_SUPERVISED)
53 if (user_id != supervised_user_manager->GetManagerUserId((*it)->email()))
55 OnSharedSettingsChange(
56 supervised_user_manager->GetUserSyncId((*it)->email()),
57 supervised_users::kChromeOSPasswordData);
61 void ManagerPasswordService::OnSharedSettingsChange(
62 const std::string& su_id,
63 const std::string& key) {
64 if (key != supervised_users::kChromeOSPasswordData)
67 SupervisedUserManager* supervised_user_manager =
68 ChromeUserManager::Get()->GetSupervisedUserManager();
69 const user_manager::User* user = supervised_user_manager->FindBySyncId(su_id);
74 const base::Value* value = settings_service_->GetValue(su_id, key);
77 LOG(WARNING) << "Got empty value from sync.";
80 const base::DictionaryValue* dict;
81 if (!value->GetAsDictionary(&dict)) {
82 LOG(WARNING) << "Got non-dictionary value from sync.";
86 SupervisedUserAuthentication* auth =
87 supervised_user_manager->GetAuthentication();
89 if (!auth->NeedPasswordChange(user->email(), dict) &&
90 !auth->HasIncompleteKey(user->email())) {
93 scoped_ptr<base::DictionaryValue> wrapper(dict->DeepCopy());
94 user_service_->GetSupervisedUsersAsync(
95 base::Bind(&ManagerPasswordService::GetSupervisedUsersCallback,
96 weak_ptr_factory_.GetWeakPtr(),
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))
110 std::string master_key;
111 std::string encryption_key;
112 std::string signature_key;
113 if (!supervised_user->GetString(SupervisedUserSyncService::kMasterKey,
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);
124 if (!supervised_user->GetString(
125 SupervisedUserSyncService::kPasswordSignatureKey, &signature_key) ||
126 !supervised_user->GetString(
127 SupervisedUserSyncService::kPasswordEncryptionKey,
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);
138 UserContext manager_key(user_id);
139 manager_key.SetKey(Key(master_key));
140 manager_key.SetIsUsingOAuth(false);
142 // As master key can have old label, leave label field empty - it will work
148 bool has_data = password_data->GetStringWithoutPathExpansion(
149 kEncryptedPassword, &new_key);
150 has_data &= password_data->GetIntegerWithoutPathExpansion(kPasswordRevision,
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);
162 cryptohome::KeyDefinition new_key_definition(
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 */,
171 new_key_definition.authorization_data.push_back(
172 cryptohome::KeyDefinition::AuthorizationData(false /* encrypt */,
176 authenticator_->AddKey(manager_key,
178 true /* replace existing */,
179 base::Bind(&ManagerPasswordService::OnAddKeySuccess,
180 weak_ptr_factory_.GetWeakPtr(),
183 Passed(&password_data)));
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";
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);
205 SupervisedUserAuthentication* auth =
206 ChromeUserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
207 int old_schema = auth->GetPasswordSchema(user_id);
208 auth->StorePasswordData(user_id, *password_data.get());
210 if (auth->HasIncompleteKey(user_id))
211 auth->MarkKeyIncomplete(user_id, false /* key is complete now */);
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(
221 base::Bind(&ManagerPasswordService::OnKeyTransformedIfNeeded,
222 weak_ptr_factory_.GetWeakPtr()));
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(
239 true /* replace existing */,
240 base::Bind(&ManagerPasswordService::OnNewManagerKeySuccess,
241 weak_ptr_factory_.GetWeakPtr(),
242 new_master_key_context));
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(
250 kLegacyCryptohomeSupervisedUserKeyLabel,
251 base::Bind(&ManagerPasswordService::OnOldSupervisedUserKeyDeleted,
252 weak_ptr_factory_.GetWeakPtr(),
253 master_key_context));
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(
262 kLegacyCryptohomeMasterKeyLabel,
263 base::Bind(&ManagerPasswordService::OnOldManagerKeyDeleted,
264 weak_ptr_factory_.GetWeakPtr(),
265 master_key_context));
268 void ManagerPasswordService::OnOldManagerKeyDeleted(
269 const UserContext& master_key_context) {
270 VLOG(1) << "Removed old master key for " << master_key_context.GetUserID();
273 void ManagerPasswordService::Shutdown() {
274 settings_service_subscription_.reset();
277 } // namespace chromeos