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