Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / supervised_user / chromeos / manager_password_service.cc
blob30f0a055b57fc86d51958dbe15e730fc4ad23d84
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"
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/legacy/supervised_user_sync_service.h"
16 #include "chrome/browser/supervised_user/supervised_user_constants.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"
23 namespace chromeos {
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) {
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()));
40 authenticator_ = ExtendedAuthenticator::Create(this);
42 SupervisedUserManager* supervised_user_manager =
43 ChromeUserManager::Get()->GetSupervisedUserManager();
45 for (const user_manager::User* user :
46 user_manager::UserManager::Get()->GetUsers()) {
47 if (user->GetType() != user_manager::USER_TYPE_SUPERVISED)
48 continue;
49 if (user_id != supervised_user_manager->GetManagerUserId(user->email()))
50 continue;
51 OnSharedSettingsChange(
52 supervised_user_manager->GetUserSyncId(user->email()),
53 supervised_users::kChromeOSPasswordData);
57 void ManagerPasswordService::OnSharedSettingsChange(
58 const std::string& su_id,
59 const std::string& key) {
60 if (key != supervised_users::kChromeOSPasswordData)
61 return;
63 SupervisedUserManager* supervised_user_manager =
64 ChromeUserManager::Get()->GetSupervisedUserManager();
65 const user_manager::User* user = supervised_user_manager->FindBySyncId(su_id);
66 // No user on device.
67 if (user == NULL)
68 return;
70 const base::Value* value = settings_service_->GetValue(su_id, key);
72 if (value == NULL) {
73 LOG(WARNING) << "Got empty value from sync.";
74 return;
76 const base::DictionaryValue* dict;
77 if (!value->GetAsDictionary(&dict)) {
78 LOG(WARNING) << "Got non-dictionary value from sync.";
79 return;
82 SupervisedUserAuthentication* auth =
83 supervised_user_manager->GetAuthentication();
85 if (!auth->NeedPasswordChange(user->email(), dict) &&
86 !auth->HasIncompleteKey(user->email())) {
87 return;
89 scoped_ptr<base::DictionaryValue> wrapper(dict->DeepCopy());
90 user_service_->GetSupervisedUsersAsync(
91 base::Bind(&ManagerPasswordService::GetSupervisedUsersCallback,
92 weak_ptr_factory_.GetWeakPtr(),
93 su_id,
94 user->email(),
95 Passed(&wrapper)));
98 void ManagerPasswordService::GetSupervisedUsersCallback(
99 const std::string& sync_su_id,
100 const std::string& user_id,
101 scoped_ptr<base::DictionaryValue> password_data,
102 const base::DictionaryValue* supervised_users) {
103 const base::DictionaryValue* supervised_user = NULL;
104 if (!supervised_users->GetDictionary(sync_su_id, &supervised_user))
105 return;
106 std::string master_key;
107 std::string encryption_key;
108 std::string signature_key;
109 if (!supervised_user->GetString(SupervisedUserSyncService::kMasterKey,
110 &master_key)) {
111 LOG(WARNING) << "Can not apply password change to " << user_id
112 << ": no master key found";
113 UMA_HISTOGRAM_ENUMERATION(
114 "ManagedUsers.ChromeOS.PasswordChange",
115 SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_NO_MASTER_KEY,
116 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
117 return;
120 if (!supervised_user->GetString(
121 SupervisedUserSyncService::kPasswordSignatureKey, &signature_key) ||
122 !supervised_user->GetString(
123 SupervisedUserSyncService::kPasswordEncryptionKey,
124 &encryption_key)) {
125 LOG(WARNING) << "Can not apply password change to " << user_id
126 << ": no signature / encryption keys.";
127 UMA_HISTOGRAM_ENUMERATION(
128 "ManagedUsers.ChromeOS.PasswordChange",
129 SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_NO_SIGNATURE_KEY,
130 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
131 return;
134 UserContext manager_key(user_id);
135 manager_key.SetKey(Key(master_key));
136 manager_key.SetIsUsingOAuth(false);
138 // As master key can have old label, leave label field empty - it will work
139 // as wildcard.
141 std::string new_key;
142 int revision;
144 bool has_data = password_data->GetStringWithoutPathExpansion(
145 kEncryptedPassword, &new_key);
146 has_data &= password_data->GetIntegerWithoutPathExpansion(kPasswordRevision,
147 &revision);
148 if (!has_data) {
149 LOG(WARNING) << "Can not apply password change to " << user_id
150 << ": incomplete password data.";
151 UMA_HISTOGRAM_ENUMERATION(
152 "ManagedUsers.ChromeOS.PasswordChange",
153 SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_NO_PASSWORD_DATA,
154 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
155 return;
158 cryptohome::KeyDefinition new_key_definition(
159 new_key,
160 kCryptohomeSupervisedUserKeyLabel,
161 cryptohome::PRIV_AUTHORIZED_UPDATE || cryptohome::PRIV_MOUNT);
162 new_key_definition.revision = revision;
163 new_key_definition.authorization_data.push_back(
164 cryptohome::KeyDefinition::AuthorizationData(true /* encrypt */,
165 false /* sign */,
166 encryption_key));
167 new_key_definition.authorization_data.push_back(
168 cryptohome::KeyDefinition::AuthorizationData(false /* encrypt */,
169 true /* sign */,
170 signature_key));
172 authenticator_->AddKey(manager_key,
173 new_key_definition,
174 true /* replace existing */,
175 base::Bind(&ManagerPasswordService::OnAddKeySuccess,
176 weak_ptr_factory_.GetWeakPtr(),
177 manager_key,
178 user_id,
179 Passed(&password_data)));
182 void ManagerPasswordService::OnAuthenticationFailure(
183 ExtendedAuthenticator::AuthState state) {
184 UMA_HISTOGRAM_ENUMERATION(
185 "ManagedUsers.ChromeOS.PasswordChange",
186 SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_MASTER_KEY_FAILURE,
187 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
188 LOG(ERROR) << "Can not apply password change, master key failure";
191 void ManagerPasswordService::OnAddKeySuccess(
192 const UserContext& master_key_context,
193 const std::string& user_id,
194 scoped_ptr<base::DictionaryValue> password_data) {
195 VLOG(0) << "Password changed for " << user_id;
196 UMA_HISTOGRAM_ENUMERATION(
197 "ManagedUsers.ChromeOS.PasswordChange",
198 SupervisedUserAuthentication::PASSWORD_CHANGED_IN_MANAGER_SESSION,
199 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
201 SupervisedUserAuthentication* auth =
202 ChromeUserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
203 int old_schema = auth->GetPasswordSchema(user_id);
204 auth->StorePasswordData(user_id, *password_data.get());
206 if (auth->HasIncompleteKey(user_id))
207 auth->MarkKeyIncomplete(user_id, false /* key is complete now */);
209 // Check if we have legacy labels for keys.
210 // TODO(antrim): Migrate it to GetLabels call once wad@ implement it.
211 if (old_schema == SupervisedUserAuthentication::SCHEMA_PLAIN) {
212 // 1) Add new manager key (using old key).
213 // 2) Remove old supervised user key.
214 // 3) Remove old manager key.
215 authenticator_->TransformKeyIfNeeded(
216 master_key_context,
217 base::Bind(&ManagerPasswordService::OnKeyTransformedIfNeeded,
218 weak_ptr_factory_.GetWeakPtr()));
222 void ManagerPasswordService::OnKeyTransformedIfNeeded(
223 const UserContext& master_key_context) {
224 const Key* const key = master_key_context.GetKey();
225 DCHECK_NE(Key::KEY_TYPE_PASSWORD_PLAIN, key->GetKeyType());
226 cryptohome::KeyDefinition new_master_key(key->GetSecret(),
227 kCryptohomeMasterKeyLabel,
228 cryptohome::PRIV_DEFAULT);
229 // Use new master key for further actions.
230 UserContext new_master_key_context = master_key_context;
231 new_master_key_context.GetKey()->SetLabel(kCryptohomeMasterKeyLabel);
232 authenticator_->AddKey(
233 master_key_context,
234 new_master_key,
235 true /* replace existing */,
236 base::Bind(&ManagerPasswordService::OnNewManagerKeySuccess,
237 weak_ptr_factory_.GetWeakPtr(),
238 new_master_key_context));
241 void ManagerPasswordService::OnNewManagerKeySuccess(
242 const UserContext& master_key_context) {
243 VLOG(1) << "Added new master key for " << master_key_context.GetUserID();
244 authenticator_->RemoveKey(
245 master_key_context,
246 kLegacyCryptohomeSupervisedUserKeyLabel,
247 base::Bind(&ManagerPasswordService::OnOldSupervisedUserKeyDeleted,
248 weak_ptr_factory_.GetWeakPtr(),
249 master_key_context));
252 void ManagerPasswordService::OnOldSupervisedUserKeyDeleted(
253 const UserContext& master_key_context) {
254 VLOG(1) << "Removed old supervised user key for "
255 << master_key_context.GetUserID();
256 authenticator_->RemoveKey(
257 master_key_context,
258 kLegacyCryptohomeMasterKeyLabel,
259 base::Bind(&ManagerPasswordService::OnOldManagerKeyDeleted,
260 weak_ptr_factory_.GetWeakPtr(),
261 master_key_context));
264 void ManagerPasswordService::OnOldManagerKeyDeleted(
265 const UserContext& master_key_context) {
266 VLOG(1) << "Removed old master key for " << master_key_context.GetUserID();
269 void ManagerPasswordService::Shutdown() {
270 settings_service_subscription_.reset();
273 } // namespace chromeos