• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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