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