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/chromeos/login/users/supervised_user_manager_impl.h" 6 7 #include "base/file_util.h" 8 #include "base/files/file_path.h" 9 #include "base/prefs/pref_registry_simple.h" 10 #include "base/prefs/pref_service.h" 11 #include "base/prefs/scoped_user_pref_update.h" 12 #include "base/strings/string_util.h" 13 #include "base/strings/stringprintf.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "base/threading/sequenced_worker_pool.h" 16 #include "base/values.h" 17 #include "chrome/browser/browser_process.h" 18 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h" 19 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h" 20 #include "chrome/browser/chromeos/login/users/user_manager_impl.h" 21 #include "chrome/browser/chromeos/profiles/profile_helper.h" 22 #include "chrome/browser/supervised_user/supervised_user_service.h" 23 #include "chrome/browser/supervised_user/supervised_user_service_factory.h" 24 #include "chromeos/settings/cros_settings_names.h" 25 #include "content/public/browser/browser_thread.h" 26 #include "google_apis/gaia/gaia_auth_util.h" 27 28 using content::BrowserThread; 29 30 namespace { 31 32 // Names for pref keys in Local State. 33 // A map from locally managed user local user id to sync user id. 34 const char kSupervisedUserSyncId[] = 35 "ManagedUserSyncId"; 36 37 // A map from locally managed user id to manager user id. 38 const char kSupervisedUserManagers[] = 39 "ManagedUserManagers"; 40 41 // A map from locally managed user id to manager display name. 42 const char kSupervisedUserManagerNames[] = 43 "ManagedUserManagerNames"; 44 45 // A map from locally managed user id to manager display e-mail. 46 const char kSupervisedUserManagerDisplayEmails[] = 47 "ManagedUserManagerDisplayEmails"; 48 49 // A vector pref of the locally managed accounts defined on this device, that 50 // had not logged in yet. 51 const char kLocallyManagedUsersFirstRun[] = "LocallyManagedUsersFirstRun"; 52 53 // A pref of the next id for locally managed users generation. 54 const char kLocallyManagedUsersNextId[] = 55 "LocallyManagedUsersNextId"; 56 57 // A pref of the next id for locally managed users generation. 58 const char kLocallyManagedUserCreationTransactionDisplayName[] = 59 "LocallyManagedUserCreationTransactionDisplayName"; 60 61 // A pref of the next id for locally managed users generation. 62 const char kLocallyManagedUserCreationTransactionUserId[] = 63 "LocallyManagedUserCreationTransactionUserId"; 64 65 // A map from user id to password schema id. 66 const char kSupervisedUserPasswordSchema[] = 67 "SupervisedUserPasswordSchema"; 68 69 // A map from user id to password salt. 70 const char kSupervisedUserPasswordSalt[] = 71 "SupervisedUserPasswordSalt"; 72 73 // A map from user id to password revision. 74 const char kSupervisedUserPasswordRevision[] = 75 "SupervisedUserPasswordRevision"; 76 77 // A map from user id to flag indicating if password should be updated upon 78 // signin. 79 const char kSupervisedUserNeedPasswordUpdate[] = 80 "SupervisedUserNeedPasswordUpdate"; 81 82 // A map from user id to flag indicating if cryptohome does not have signature 83 // key. 84 const char kSupervisedUserIncompleteKey[] = "SupervisedUserHasIncompleteKey"; 85 86 std::string LoadSyncToken(base::FilePath profile_dir) { 87 std::string token; 88 base::FilePath token_file = 89 profile_dir.Append(chromeos::kSupervisedUserTokenFilename); 90 VLOG(1) << "Loading" << token_file.value(); 91 if (!base::ReadFileToString(token_file, &token)) 92 return std::string(); 93 return token; 94 } 95 96 } // namespace 97 98 namespace chromeos { 99 100 const char kSchemaVersion[] = "SchemaVersion"; 101 const char kPasswordRevision[] = "PasswordRevision"; 102 const char kSalt[] = "PasswordSalt"; 103 const char kPasswordSignature[] = "PasswordSignature"; 104 const char kEncryptedPassword[] = "EncryptedPassword"; 105 const char kRequirePasswordUpdate[] = "RequirePasswordUpdate"; 106 const char kHasIncompleteKey[] = "HasIncompleteKey"; 107 const char kPasswordEncryptionKey[] = "password.hmac.encryption"; 108 const char kPasswordSignatureKey[] = "password.hmac.signature"; 109 110 const char kPasswordUpdateFile[] = "password.update"; 111 const int kMinPasswordRevision = 1; 112 113 // static 114 void SupervisedUserManager::RegisterPrefs(PrefRegistrySimple* registry) { 115 registry->RegisterListPref(kLocallyManagedUsersFirstRun); 116 registry->RegisterIntegerPref(kLocallyManagedUsersNextId, 0); 117 registry->RegisterStringPref( 118 kLocallyManagedUserCreationTransactionDisplayName, ""); 119 registry->RegisterStringPref( 120 kLocallyManagedUserCreationTransactionUserId, ""); 121 registry->RegisterDictionaryPref(kSupervisedUserSyncId); 122 registry->RegisterDictionaryPref(kSupervisedUserManagers); 123 registry->RegisterDictionaryPref(kSupervisedUserManagerNames); 124 registry->RegisterDictionaryPref(kSupervisedUserManagerDisplayEmails); 125 126 registry->RegisterDictionaryPref(kSupervisedUserPasswordSchema); 127 registry->RegisterDictionaryPref(kSupervisedUserPasswordSalt); 128 registry->RegisterDictionaryPref(kSupervisedUserPasswordRevision); 129 130 registry->RegisterDictionaryPref(kSupervisedUserNeedPasswordUpdate); 131 registry->RegisterDictionaryPref(kSupervisedUserIncompleteKey); 132 } 133 134 SupervisedUserManagerImpl::SupervisedUserManagerImpl(UserManagerImpl* owner) 135 : owner_(owner), 136 cros_settings_(CrosSettings::Get()) { 137 // SupervisedUserManager instance should be used only on UI thread. 138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 139 authentication_.reset(new SupervisedUserAuthentication(this)); 140 } 141 142 SupervisedUserManagerImpl::~SupervisedUserManagerImpl() { 143 } 144 145 std::string SupervisedUserManagerImpl::GenerateUserId() { 146 int counter = g_browser_process->local_state()-> 147 GetInteger(kLocallyManagedUsersNextId); 148 std::string id; 149 bool user_exists; 150 do { 151 id = base::StringPrintf("%d@%s", counter, 152 UserManager::kLocallyManagedUserDomain); 153 counter++; 154 user_exists = (NULL != owner_->FindUser(id)); 155 DCHECK(!user_exists); 156 if (user_exists) { 157 LOG(ERROR) << "Supervised user with id " << id << " already exists."; 158 } 159 } while (user_exists); 160 161 g_browser_process->local_state()-> 162 SetInteger(kLocallyManagedUsersNextId, counter); 163 164 g_browser_process->local_state()->CommitPendingWrite(); 165 return id; 166 } 167 168 bool SupervisedUserManagerImpl::HasSupervisedUsers( 169 const std::string& manager_id) const { 170 const UserList& users = owner_->GetUsers(); 171 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) { 172 if ((*it)->GetType() == User::USER_TYPE_LOCALLY_MANAGED) { 173 if (manager_id == GetManagerUserId((*it)->email())) 174 return true; 175 } 176 } 177 return false; 178 } 179 180 const User* SupervisedUserManagerImpl::CreateUserRecord( 181 const std::string& manager_id, 182 const std::string& local_user_id, 183 const std::string& sync_user_id, 184 const base::string16& display_name) { 185 const User* user = FindByDisplayName(display_name); 186 DCHECK(!user); 187 if (user) 188 return user; 189 const User* manager = owner_->FindUser(manager_id); 190 CHECK(manager); 191 192 PrefService* local_state = g_browser_process->local_state(); 193 194 User* new_user = User::CreateLocallyManagedUser(local_user_id); 195 196 owner_->AddUserRecord(new_user); 197 198 ListPrefUpdate prefs_new_users_update(local_state, 199 kLocallyManagedUsersFirstRun); 200 DictionaryPrefUpdate sync_id_update(local_state, kSupervisedUserSyncId); 201 DictionaryPrefUpdate manager_update(local_state, kSupervisedUserManagers); 202 DictionaryPrefUpdate manager_name_update(local_state, 203 kSupervisedUserManagerNames); 204 DictionaryPrefUpdate manager_email_update( 205 local_state, 206 kSupervisedUserManagerDisplayEmails); 207 208 prefs_new_users_update->Insert(0, new base::StringValue(local_user_id)); 209 210 sync_id_update->SetWithoutPathExpansion(local_user_id, 211 new base::StringValue(sync_user_id)); 212 manager_update->SetWithoutPathExpansion(local_user_id, 213 new base::StringValue(manager->email())); 214 manager_name_update->SetWithoutPathExpansion(local_user_id, 215 new base::StringValue(manager->GetDisplayName())); 216 manager_email_update->SetWithoutPathExpansion(local_user_id, 217 new base::StringValue(manager->display_email())); 218 219 owner_->SaveUserDisplayName(local_user_id, display_name); 220 221 g_browser_process->local_state()->CommitPendingWrite(); 222 return new_user; 223 } 224 225 std::string SupervisedUserManagerImpl::GetUserSyncId(const std::string& user_id) 226 const { 227 std::string result; 228 GetUserStringValue(user_id, kSupervisedUserSyncId, &result); 229 return result; 230 } 231 232 base::string16 SupervisedUserManagerImpl::GetManagerDisplayName( 233 const std::string& user_id) const { 234 PrefService* local_state = g_browser_process->local_state(); 235 const base::DictionaryValue* manager_names = 236 local_state->GetDictionary(kSupervisedUserManagerNames); 237 base::string16 result; 238 if (manager_names->GetStringWithoutPathExpansion(user_id, &result) && 239 !result.empty()) 240 return result; 241 return base::UTF8ToUTF16(GetManagerDisplayEmail(user_id)); 242 } 243 244 std::string SupervisedUserManagerImpl::GetManagerUserId( 245 const std::string& user_id) const { 246 std::string result; 247 GetUserStringValue(user_id, kSupervisedUserManagers, &result); 248 return result; 249 } 250 251 std::string SupervisedUserManagerImpl::GetManagerDisplayEmail( 252 const std::string& user_id) const { 253 std::string result; 254 if (GetUserStringValue(user_id, 255 kSupervisedUserManagerDisplayEmails, 256 &result) && 257 !result.empty()) 258 return result; 259 return GetManagerUserId(user_id); 260 } 261 262 void SupervisedUserManagerImpl::GetPasswordInformation( 263 const std::string& user_id, 264 base::DictionaryValue* result) { 265 int value; 266 if (GetUserIntegerValue(user_id, kSupervisedUserPasswordSchema, &value)) 267 result->SetIntegerWithoutPathExpansion(kSchemaVersion, value); 268 if (GetUserIntegerValue(user_id, kSupervisedUserPasswordRevision, &value)) 269 result->SetIntegerWithoutPathExpansion(kPasswordRevision, value); 270 271 bool flag; 272 if (GetUserBooleanValue(user_id, kSupervisedUserNeedPasswordUpdate, &flag)) 273 result->SetBooleanWithoutPathExpansion(kRequirePasswordUpdate, flag); 274 if (GetUserBooleanValue(user_id, kSupervisedUserIncompleteKey, &flag)) 275 result->SetBooleanWithoutPathExpansion(kHasIncompleteKey, flag); 276 277 std::string salt; 278 if (GetUserStringValue(user_id, kSupervisedUserPasswordSalt, &salt)) 279 result->SetStringWithoutPathExpansion(kSalt, salt); 280 } 281 282 void SupervisedUserManagerImpl::SetPasswordInformation( 283 const std::string& user_id, 284 const base::DictionaryValue* password_info) { 285 int value; 286 if (password_info->GetIntegerWithoutPathExpansion(kSchemaVersion, &value)) 287 SetUserIntegerValue(user_id, kSupervisedUserPasswordSchema, value); 288 if (password_info->GetIntegerWithoutPathExpansion(kPasswordRevision, &value)) 289 SetUserIntegerValue(user_id, kSupervisedUserPasswordRevision, value); 290 291 bool flag; 292 if (password_info->GetBooleanWithoutPathExpansion(kRequirePasswordUpdate, 293 &flag)) { 294 SetUserBooleanValue(user_id, kSupervisedUserNeedPasswordUpdate, flag); 295 } 296 if (password_info->GetBooleanWithoutPathExpansion(kHasIncompleteKey, &flag)) 297 SetUserBooleanValue(user_id, kSupervisedUserIncompleteKey, flag); 298 299 std::string salt; 300 if (password_info->GetStringWithoutPathExpansion(kSalt, &salt)) 301 SetUserStringValue(user_id, kSupervisedUserPasswordSalt, salt); 302 g_browser_process->local_state()->CommitPendingWrite(); 303 } 304 305 bool SupervisedUserManagerImpl::GetUserStringValue( 306 const std::string& user_id, 307 const char* key, 308 std::string* out_value) const { 309 PrefService* local_state = g_browser_process->local_state(); 310 const base::DictionaryValue* dictionary = local_state->GetDictionary(key); 311 return dictionary->GetStringWithoutPathExpansion(user_id, out_value); 312 } 313 314 bool SupervisedUserManagerImpl::GetUserIntegerValue( 315 const std::string& user_id, 316 const char* key, 317 int* out_value) const { 318 PrefService* local_state = g_browser_process->local_state(); 319 const base::DictionaryValue* dictionary = local_state->GetDictionary(key); 320 return dictionary->GetIntegerWithoutPathExpansion(user_id, out_value); 321 } 322 323 bool SupervisedUserManagerImpl::GetUserBooleanValue(const std::string& user_id, 324 const char* key, 325 bool* out_value) const { 326 PrefService* local_state = g_browser_process->local_state(); 327 const base::DictionaryValue* dictionary = local_state->GetDictionary(key); 328 return dictionary->GetBooleanWithoutPathExpansion(user_id, out_value); 329 } 330 331 void SupervisedUserManagerImpl::SetUserStringValue( 332 const std::string& user_id, 333 const char* key, 334 const std::string& value) { 335 PrefService* local_state = g_browser_process->local_state(); 336 DictionaryPrefUpdate update(local_state, key); 337 update->SetStringWithoutPathExpansion(user_id, value); 338 } 339 340 void SupervisedUserManagerImpl::SetUserIntegerValue( 341 const std::string& user_id, 342 const char* key, 343 const int value) { 344 PrefService* local_state = g_browser_process->local_state(); 345 DictionaryPrefUpdate update(local_state, key); 346 update->SetIntegerWithoutPathExpansion(user_id, value); 347 } 348 349 void SupervisedUserManagerImpl::SetUserBooleanValue(const std::string& user_id, 350 const char* key, 351 const bool value) { 352 PrefService* local_state = g_browser_process->local_state(); 353 DictionaryPrefUpdate update(local_state, key); 354 update->SetBooleanWithoutPathExpansion(user_id, value); 355 } 356 357 const User* SupervisedUserManagerImpl::FindByDisplayName( 358 const base::string16& display_name) const { 359 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 360 const UserList& users = owner_->GetUsers(); 361 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) { 362 if (((*it)->GetType() == User::USER_TYPE_LOCALLY_MANAGED) && 363 ((*it)->display_name() == display_name)) { 364 return *it; 365 } 366 } 367 return NULL; 368 } 369 370 const User* SupervisedUserManagerImpl::FindBySyncId( 371 const std::string& sync_id) const { 372 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 373 const UserList& users = owner_->GetUsers(); 374 for (UserList::const_iterator it = users.begin(); it != users.end(); ++it) { 375 if (((*it)->GetType() == User::USER_TYPE_LOCALLY_MANAGED) && 376 (GetUserSyncId((*it)->email()) == sync_id)) { 377 return *it; 378 } 379 } 380 return NULL; 381 } 382 383 void SupervisedUserManagerImpl::StartCreationTransaction( 384 const base::string16& display_name) { 385 g_browser_process->local_state()-> 386 SetString(kLocallyManagedUserCreationTransactionDisplayName, 387 base::UTF16ToASCII(display_name)); 388 g_browser_process->local_state()->CommitPendingWrite(); 389 } 390 391 void SupervisedUserManagerImpl::SetCreationTransactionUserId( 392 const std::string& email) { 393 g_browser_process->local_state()-> 394 SetString(kLocallyManagedUserCreationTransactionUserId, 395 email); 396 g_browser_process->local_state()->CommitPendingWrite(); 397 } 398 399 void SupervisedUserManagerImpl::CommitCreationTransaction() { 400 g_browser_process->local_state()-> 401 ClearPref(kLocallyManagedUserCreationTransactionDisplayName); 402 g_browser_process->local_state()-> 403 ClearPref(kLocallyManagedUserCreationTransactionUserId); 404 g_browser_process->local_state()->CommitPendingWrite(); 405 } 406 407 bool SupervisedUserManagerImpl::HasFailedUserCreationTransaction() { 408 return !(g_browser_process->local_state()-> 409 GetString(kLocallyManagedUserCreationTransactionDisplayName). 410 empty()); 411 } 412 413 void SupervisedUserManagerImpl::RollbackUserCreationTransaction() { 414 PrefService* prefs = g_browser_process->local_state(); 415 416 std::string display_name = prefs-> 417 GetString(kLocallyManagedUserCreationTransactionDisplayName); 418 std::string user_id = prefs-> 419 GetString(kLocallyManagedUserCreationTransactionUserId); 420 421 LOG(WARNING) << "Cleaning up transaction for " 422 << display_name << "/" << user_id; 423 424 if (user_id.empty()) { 425 // Not much to do - just remove transaction. 426 prefs->ClearPref(kLocallyManagedUserCreationTransactionDisplayName); 427 prefs->CommitPendingWrite(); 428 return; 429 } 430 431 if (gaia::ExtractDomainName(user_id) != 432 UserManager::kLocallyManagedUserDomain) { 433 LOG(WARNING) << "Clean up transaction for non-locally managed user found :" 434 << user_id << ", will not remove data"; 435 prefs->ClearPref(kLocallyManagedUserCreationTransactionDisplayName); 436 prefs->ClearPref(kLocallyManagedUserCreationTransactionUserId); 437 prefs->CommitPendingWrite(); 438 return; 439 } 440 owner_->RemoveNonOwnerUserInternal(user_id, NULL); 441 442 prefs->ClearPref(kLocallyManagedUserCreationTransactionDisplayName); 443 prefs->ClearPref(kLocallyManagedUserCreationTransactionUserId); 444 prefs->CommitPendingWrite(); 445 } 446 447 void SupervisedUserManagerImpl::RemoveNonCryptohomeData( 448 const std::string& user_id) { 449 PrefService* prefs = g_browser_process->local_state(); 450 ListPrefUpdate prefs_new_users_update(prefs, kLocallyManagedUsersFirstRun); 451 prefs_new_users_update->Remove(base::StringValue(user_id), NULL); 452 453 CleanPref(user_id, kSupervisedUserSyncId); 454 CleanPref(user_id, kSupervisedUserManagers); 455 CleanPref(user_id, kSupervisedUserManagerNames); 456 CleanPref(user_id, kSupervisedUserManagerDisplayEmails); 457 CleanPref(user_id, kSupervisedUserPasswordSalt); 458 CleanPref(user_id, kSupervisedUserPasswordSchema); 459 CleanPref(user_id, kSupervisedUserPasswordRevision); 460 CleanPref(user_id, kSupervisedUserNeedPasswordUpdate); 461 CleanPref(user_id, kSupervisedUserIncompleteKey); 462 } 463 464 void SupervisedUserManagerImpl::CleanPref(const std::string& user_id, 465 const char* key) { 466 PrefService* prefs = g_browser_process->local_state(); 467 DictionaryPrefUpdate dict_update(prefs, key); 468 dict_update->RemoveWithoutPathExpansion(user_id, NULL); 469 } 470 471 bool SupervisedUserManagerImpl::CheckForFirstRun(const std::string& user_id) { 472 ListPrefUpdate prefs_new_users_update(g_browser_process->local_state(), 473 kLocallyManagedUsersFirstRun); 474 return prefs_new_users_update->Remove(base::StringValue(user_id), NULL); 475 } 476 477 void SupervisedUserManagerImpl::UpdateManagerName(const std::string& manager_id, 478 const base::string16& new_display_name) { 479 PrefService* local_state = g_browser_process->local_state(); 480 481 const base::DictionaryValue* manager_ids = 482 local_state->GetDictionary(kSupervisedUserManagers); 483 484 DictionaryPrefUpdate manager_name_update(local_state, 485 kSupervisedUserManagerNames); 486 for (base::DictionaryValue::Iterator it(*manager_ids); !it.IsAtEnd(); 487 it.Advance()) { 488 std::string user_id; 489 bool has_manager_id = it.value().GetAsString(&user_id); 490 DCHECK(has_manager_id); 491 if (user_id == manager_id) { 492 manager_name_update->SetWithoutPathExpansion( 493 it.key(), 494 new base::StringValue(new_display_name)); 495 } 496 } 497 } 498 499 SupervisedUserAuthentication* SupervisedUserManagerImpl::GetAuthentication() { 500 return authentication_.get(); 501 } 502 503 void SupervisedUserManagerImpl::LoadSupervisedUserToken( 504 Profile* profile, 505 const LoadTokenCallback& callback) { 506 // TODO(antrim): use profile->GetPath() once we sure it is safe. 507 base::FilePath profile_dir = ProfileHelper::GetProfilePathByUserIdHash( 508 UserManager::Get()->GetUserByProfile(profile)->username_hash()); 509 PostTaskAndReplyWithResult( 510 content::BrowserThread::GetBlockingPool(), 511 FROM_HERE, 512 base::Bind(&LoadSyncToken, profile_dir), 513 callback); 514 } 515 516 void SupervisedUserManagerImpl::ConfigureSyncWithToken( 517 Profile* profile, 518 const std::string& token) { 519 if (!token.empty()) 520 SupervisedUserServiceFactory::GetForProfile(profile)->InitSync(token); 521 } 522 523 } // namespace chromeos 524