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