manager_password_service.cc revision 29b820f8d84e3bc97d62552e54923c42407f2f29
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_ = ExtendedAuthenticator::Create(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 new_key_definition.authorization_data.push_back( 168 cryptohome::KeyDefinition::AuthorizationData(true /* encrypt */, 169 false /* sign */, 170 encryption_key)); 171 new_key_definition.authorization_data.push_back( 172 cryptohome::KeyDefinition::AuthorizationData(false /* encrypt */, 173 true /* sign */, 174 signature_key)); 175 176 authenticator_->AddKey(manager_key, 177 new_key_definition, 178 true /* replace existing */, 179 base::Bind(&ManagerPasswordService::OnAddKeySuccess, 180 weak_ptr_factory_.GetWeakPtr(), 181 manager_key, 182 user_id, 183 Passed(&password_data))); 184} 185 186void ManagerPasswordService::OnAuthenticationFailure( 187 ExtendedAuthenticator::AuthState state) { 188 UMA_HISTOGRAM_ENUMERATION( 189 "ManagedUsers.ChromeOS.PasswordChange", 190 SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_MASTER_KEY_FAILURE, 191 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE); 192 LOG(ERROR) << "Can not apply password change, master key failure"; 193} 194 195void ManagerPasswordService::OnAddKeySuccess( 196 const UserContext& master_key_context, 197 const std::string& user_id, 198 scoped_ptr<base::DictionaryValue> password_data) { 199 VLOG(0) << "Password changed for " << user_id; 200 UMA_HISTOGRAM_ENUMERATION( 201 "ManagedUsers.ChromeOS.PasswordChange", 202 SupervisedUserAuthentication::PASSWORD_CHANGED_IN_MANAGER_SESSION, 203 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE); 204 205 SupervisedUserAuthentication* auth = 206 ChromeUserManager::Get()->GetSupervisedUserManager()->GetAuthentication(); 207 int old_schema = auth->GetPasswordSchema(user_id); 208 auth->StorePasswordData(user_id, *password_data.get()); 209 210 if (auth->HasIncompleteKey(user_id)) 211 auth->MarkKeyIncomplete(user_id, false /* key is complete now */); 212 213 // Check if we have legacy labels for keys. 214 // TODO(antrim): Migrate it to GetLabels call once wad@ implement it. 215 if (old_schema == SupervisedUserAuthentication::SCHEMA_PLAIN) { 216 // 1) Add new manager key (using old key). 217 // 2) Remove old supervised user key. 218 // 3) Remove old manager key. 219 authenticator_->TransformKeyIfNeeded( 220 master_key_context, 221 base::Bind(&ManagerPasswordService::OnKeyTransformedIfNeeded, 222 weak_ptr_factory_.GetWeakPtr())); 223 } 224} 225 226void ManagerPasswordService::OnKeyTransformedIfNeeded( 227 const UserContext& master_key_context) { 228 const Key* const key = master_key_context.GetKey(); 229 DCHECK_NE(Key::KEY_TYPE_PASSWORD_PLAIN, key->GetKeyType()); 230 cryptohome::KeyDefinition new_master_key(key->GetSecret(), 231 kCryptohomeMasterKeyLabel, 232 cryptohome::PRIV_DEFAULT); 233 // Use new master key for further actions. 234 UserContext new_master_key_context = master_key_context; 235 new_master_key_context.GetKey()->SetLabel(kCryptohomeMasterKeyLabel); 236 authenticator_->AddKey( 237 master_key_context, 238 new_master_key, 239 true /* replace existing */, 240 base::Bind(&ManagerPasswordService::OnNewManagerKeySuccess, 241 weak_ptr_factory_.GetWeakPtr(), 242 new_master_key_context)); 243} 244 245void ManagerPasswordService::OnNewManagerKeySuccess( 246 const UserContext& master_key_context) { 247 VLOG(1) << "Added new master key for " << master_key_context.GetUserID(); 248 authenticator_->RemoveKey( 249 master_key_context, 250 kLegacyCryptohomeSupervisedUserKeyLabel, 251 base::Bind(&ManagerPasswordService::OnOldSupervisedUserKeyDeleted, 252 weak_ptr_factory_.GetWeakPtr(), 253 master_key_context)); 254} 255 256void ManagerPasswordService::OnOldSupervisedUserKeyDeleted( 257 const UserContext& master_key_context) { 258 VLOG(1) << "Removed old supervised user key for " 259 << master_key_context.GetUserID(); 260 authenticator_->RemoveKey( 261 master_key_context, 262 kLegacyCryptohomeMasterKeyLabel, 263 base::Bind(&ManagerPasswordService::OnOldManagerKeyDeleted, 264 weak_ptr_factory_.GetWeakPtr(), 265 master_key_context)); 266} 267 268void ManagerPasswordService::OnOldManagerKeyDeleted( 269 const UserContext& master_key_context) { 270 VLOG(1) << "Removed old master key for " << master_key_context.GetUserID(); 271} 272 273void ManagerPasswordService::Shutdown() { 274 settings_service_subscription_.reset(); 275} 276 277} // namespace chromeos 278