manager_password_service.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 21namespace chromeos { 22 23ManagerPasswordService::ManagerPasswordService() : weak_ptr_factory_(this) {} 24 25ManagerPasswordService::~ManagerPasswordService() {} 26 27void 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 58void 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 99void 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 178void 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 187void 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 218void 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 237void 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 248void 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 260void ManagerPasswordService::OnOldManagerKeyDeleted( 261 const UserContext& master_key_context) { 262 VLOG(1) << "Removed old master key for " << master_key_context.GetUserID(); 263} 264 265void ManagerPasswordService::Shutdown() { 266 settings_service_subscription_.reset(); 267} 268 269} // namespace chromeos 270