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/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"
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 for (const user_manager::User
* user
:
46 user_manager::UserManager::Get()->GetUsers()) {
47 if (user
->GetType() != user_manager::USER_TYPE_SUPERVISED
)
49 if (user_id
!= supervised_user_manager
->GetManagerUserId(user
->email()))
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
)
63 SupervisedUserManager
* supervised_user_manager
=
64 ChromeUserManager::Get()->GetSupervisedUserManager();
65 const user_manager::User
* user
= supervised_user_manager
->FindBySyncId(su_id
);
70 const base::Value
* value
= settings_service_
->GetValue(su_id
, key
);
73 LOG(WARNING
) << "Got empty value from sync.";
76 const base::DictionaryValue
* dict
;
77 if (!value
->GetAsDictionary(&dict
)) {
78 LOG(WARNING
) << "Got non-dictionary value from sync.";
82 SupervisedUserAuthentication
* auth
=
83 supervised_user_manager
->GetAuthentication();
85 if (!auth
->NeedPasswordChange(user
->email(), dict
) &&
86 !auth
->HasIncompleteKey(user
->email())) {
89 scoped_ptr
<base::DictionaryValue
> wrapper(dict
->DeepCopy());
90 user_service_
->GetSupervisedUsersAsync(
91 base::Bind(&ManagerPasswordService::GetSupervisedUsersCallback
,
92 weak_ptr_factory_
.GetWeakPtr(),
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
))
106 std::string master_key
;
107 std::string encryption_key
;
108 std::string signature_key
;
109 if (!supervised_user
->GetString(SupervisedUserSyncService::kMasterKey
,
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
);
120 if (!supervised_user
->GetString(
121 SupervisedUserSyncService::kPasswordSignatureKey
, &signature_key
) ||
122 !supervised_user
->GetString(
123 SupervisedUserSyncService::kPasswordEncryptionKey
,
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
);
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
144 bool has_data
= password_data
->GetStringWithoutPathExpansion(
145 kEncryptedPassword
, &new_key
);
146 has_data
&= password_data
->GetIntegerWithoutPathExpansion(kPasswordRevision
,
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
);
158 cryptohome::KeyDefinition
new_key_definition(
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 */,
167 new_key_definition
.authorization_data
.push_back(
168 cryptohome::KeyDefinition::AuthorizationData(false /* encrypt */,
172 authenticator_
->AddKey(manager_key
,
174 true /* replace existing */,
175 base::Bind(&ManagerPasswordService::OnAddKeySuccess
,
176 weak_ptr_factory_
.GetWeakPtr(),
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(
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(
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(
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(
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