Home | History | Annotate | Download | only in managed
      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/managed/managed_user_creation_controller_new.h"
      6 
      7 #include "base/base64.h"
      8 #include "base/bind.h"
      9 #include "base/file_util.h"
     10 #include "base/files/file_path.h"
     11 #include "base/strings/string_number_conversions.h"
     12 #include "base/strings/string_util.h"
     13 #include "base/sys_info.h"
     14 #include "base/task_runner_util.h"
     15 #include "base/threading/sequenced_worker_pool.h"
     16 #include "base/values.h"
     17 #include "chrome/browser/chromeos/login/auth/key.h"
     18 #include "chrome/browser/chromeos/login/auth/mount_manager.h"
     19 #include "chrome/browser/chromeos/login/auth/user_context.h"
     20 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h"
     21 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h"
     22 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
     23 #include "chrome/browser/chromeos/login/users/user.h"
     24 #include "chrome/browser/chromeos/login/users/user_manager.h"
     25 #include "chrome/browser/lifetime/application_lifetime.h"
     26 #include "chrome/browser/sync/profile_sync_service.h"
     27 #include "chrome/browser/sync/profile_sync_service_factory.h"
     28 #include "chromeos/cryptohome/cryptohome_parameters.h"
     29 #include "chromeos/dbus/dbus_thread_manager.h"
     30 #include "chromeos/dbus/session_manager_client.h"
     31 #include "content/public/browser/browser_thread.h"
     32 #include "content/public/browser/user_metrics.h"
     33 #include "crypto/random.h"
     34 #include "google_apis/gaia/google_service_auth_error.h"
     35 
     36 namespace chromeos {
     37 
     38 namespace {
     39 
     40 const int kUserCreationTimeoutSeconds = 30;  // 30 seconds.
     41 
     42 bool StoreManagedUserFiles(const std::string& token,
     43                            const base::FilePath& base_path) {
     44   if (!base::SysInfo::IsRunningOnChromeOS()) {
     45     // If running on desktop, cryptohome stub does not create home directory.
     46     base::CreateDirectory(base_path);
     47   }
     48   base::FilePath token_file = base_path.Append(kSupervisedUserTokenFilename);
     49   int bytes = base::WriteFile(token_file, token.c_str(), token.length());
     50   return bytes >= 0;
     51 }
     52 
     53 }  // namespace
     54 
     55 ManagedUserCreationControllerNew::ManagedUserCreationControllerNew(
     56     ManagedUserCreationControllerNew::StatusConsumer* consumer,
     57     const std::string& manager_id)
     58     : ManagedUserCreationController(consumer),
     59       stage_(STAGE_INITIAL),
     60       weak_factory_(this) {
     61   creation_context_.reset(
     62       new ManagedUserCreationControllerNew::UserCreationContext());
     63   creation_context_->manager_id = manager_id;
     64 }
     65 
     66 ManagedUserCreationControllerNew::~ManagedUserCreationControllerNew() {}
     67 
     68 ManagedUserCreationControllerNew::UserCreationContext::UserCreationContext() {}
     69 
     70 ManagedUserCreationControllerNew::UserCreationContext::~UserCreationContext() {}
     71 
     72 void ManagedUserCreationControllerNew::SetManagerProfile(
     73     Profile* manager_profile) {
     74   creation_context_->manager_profile = manager_profile;
     75 }
     76 
     77 Profile* ManagedUserCreationControllerNew::GetManagerProfile() {
     78   return creation_context_->manager_profile;
     79 }
     80 
     81 void ManagedUserCreationControllerNew::StartCreation(
     82     const base::string16& display_name,
     83     const std::string& password,
     84     int avatar_index) {
     85   DCHECK(creation_context_);
     86   creation_context_->creation_type = NEW_USER;
     87   creation_context_->display_name = display_name;
     88   creation_context_->password = password;
     89   creation_context_->avatar_index = avatar_index;
     90   StartCreationImpl();
     91 }
     92 
     93 void ManagedUserCreationControllerNew::StartImport(
     94     const base::string16& display_name,
     95     const std::string& password,
     96     int avatar_index,
     97     const std::string& sync_id,
     98     const std::string& master_key) {
     99   DCHECK(creation_context_);
    100   creation_context_->creation_type = USER_IMPORT_OLD;
    101 
    102   creation_context_->display_name = display_name;
    103   creation_context_->password = password;
    104   creation_context_->avatar_index = avatar_index;
    105 
    106   creation_context_->sync_user_id = sync_id;
    107 
    108   creation_context_->master_key = master_key;
    109   StartCreationImpl();
    110 }
    111 
    112 void ManagedUserCreationControllerNew::StartImport(
    113     const base::string16& display_name,
    114     int avatar_index,
    115     const std::string& sync_id,
    116     const std::string& master_key,
    117     const base::DictionaryValue* password_data,
    118     const std::string& encryption_key,
    119     const std::string& signature_key) {
    120   DCHECK(creation_context_);
    121   creation_context_->creation_type = USER_IMPORT_NEW;
    122 
    123   creation_context_->display_name = display_name;
    124 
    125   creation_context_->avatar_index = avatar_index;
    126 
    127   creation_context_->sync_user_id = sync_id;
    128 
    129   creation_context_->master_key = master_key;
    130 
    131   password_data->GetStringWithoutPathExpansion(
    132       kEncryptedPassword, &creation_context_->salted_password);
    133 
    134   creation_context_->signature_key = signature_key;
    135   creation_context_->encryption_key = encryption_key;
    136 
    137   creation_context_->password_data.MergeDictionary(password_data);
    138 
    139   StartCreationImpl();
    140 }
    141 
    142 void ManagedUserCreationControllerNew::StartCreationImpl() {
    143   DCHECK(creation_context_);
    144   DCHECK_EQ(STAGE_INITIAL, stage_);
    145   VLOG(1) << "Starting supervised user creation";
    146   VLOG(1) << " Phase 1 : Prepare keys";
    147 
    148   SupervisedUserManager* manager =
    149       UserManager::Get()->GetSupervisedUserManager();
    150   manager->StartCreationTransaction(creation_context_->display_name);
    151 
    152   creation_context_->local_user_id = manager->GenerateUserId();
    153   if (creation_context_->creation_type == NEW_USER) {
    154     creation_context_->sync_user_id =
    155         SupervisedUserRegistrationUtility::GenerateNewSupervisedUserId();
    156   }
    157 
    158   manager->SetCreationTransactionUserId(creation_context_->local_user_id);
    159 
    160   stage_ = TRANSACTION_STARTED;
    161 
    162   manager->CreateUserRecord(creation_context_->manager_id,
    163                             creation_context_->local_user_id,
    164                             creation_context_->sync_user_id,
    165                             creation_context_->display_name);
    166 
    167   SupervisedUserAuthentication* authentication =
    168       UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
    169 
    170   // When importing M35+ users we need only to store data, for all other cases
    171   // we need to create some keys.
    172   if (creation_context_->creation_type != USER_IMPORT_NEW) {
    173     // Of all required keys old imported users have only master key.
    174     // Otherwise they are the same as newly created users in terms of keys.
    175     if (creation_context_->creation_type == NEW_USER) {
    176       creation_context_->master_key = authentication->GenerateMasterKey();
    177     }
    178 
    179     base::DictionaryValue extra;
    180     authentication->FillDataForNewUser(creation_context_->local_user_id,
    181                                        creation_context_->password,
    182                                        &creation_context_->password_data,
    183                                        &extra);
    184     creation_context_->password_data.GetStringWithoutPathExpansion(
    185         kEncryptedPassword, &creation_context_->salted_password);
    186     extra.GetStringWithoutPathExpansion(kPasswordEncryptionKey,
    187                                         &creation_context_->encryption_key);
    188     extra.GetStringWithoutPathExpansion(kPasswordSignatureKey,
    189                                         &creation_context_->signature_key);
    190   }
    191 
    192   authentication->StorePasswordData(creation_context_->local_user_id,
    193                                     creation_context_->password_data);
    194   stage_ = KEYS_GENERATED;
    195 
    196   VLOG(1) << " Phase 2 : Create cryptohome";
    197 
    198   timeout_timer_.Start(
    199       FROM_HERE,
    200       base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds),
    201       this,
    202       &ManagedUserCreationControllerNew::CreationTimedOut);
    203   authenticator_ = new ExtendedAuthenticator(this);
    204   UserContext user_context;
    205   user_context.SetKey(Key(creation_context_->master_key));
    206   authenticator_->TransformKeyIfNeeded(
    207       user_context,
    208       base::Bind(&ManagedUserCreationControllerNew::OnKeyTransformedIfNeeded,
    209                  weak_factory_.GetWeakPtr()));
    210 }
    211 
    212 void ManagedUserCreationControllerNew::OnKeyTransformedIfNeeded(
    213     const UserContext& user_context) {
    214   VLOG(1) << " Phase 2.1 : Got hashed master key";
    215   creation_context_->salted_master_key = user_context.GetKey()->GetSecret();
    216 
    217   // Create home dir with two keys.
    218   std::vector<cryptohome::KeyDefinition> keys;
    219 
    220   // Main key is the master key. Just as keys for plain GAIA users, it is salted
    221   // with system salt. It has all usual privileges.
    222   cryptohome::KeyDefinition master_key(creation_context_->salted_master_key,
    223                                        kCryptohomeMasterKeyLabel,
    224                                        cryptohome::PRIV_DEFAULT);
    225 
    226   keys.push_back(master_key);
    227   authenticator_->CreateMount(
    228       creation_context_->local_user_id,
    229       keys,
    230       base::Bind(&ManagedUserCreationControllerNew::OnMountSuccess,
    231                  weak_factory_.GetWeakPtr()));
    232 }
    233 
    234 void ManagedUserCreationControllerNew::OnAuthenticationFailure(
    235     ExtendedAuthenticator::AuthState error) {
    236   timeout_timer_.Stop();
    237   ErrorCode code = NO_ERROR;
    238   switch (error) {
    239     case ManagedUserAuthenticator::NO_MOUNT:
    240       code = CRYPTOHOME_NO_MOUNT;
    241       break;
    242     case ManagedUserAuthenticator::FAILED_MOUNT:
    243       code = CRYPTOHOME_FAILED_MOUNT;
    244       break;
    245     case ManagedUserAuthenticator::FAILED_TPM:
    246       code = CRYPTOHOME_FAILED_TPM;
    247       break;
    248     default:
    249       NOTREACHED();
    250   }
    251   stage_ = STAGE_ERROR;
    252   if (consumer_)
    253     consumer_->OnCreationError(code);
    254 }
    255 
    256 void ManagedUserCreationControllerNew::OnMountSuccess(
    257     const std::string& mount_hash) {
    258   DCHECK(creation_context_);
    259   DCHECK_EQ(KEYS_GENERATED, stage_);
    260   VLOG(1) << " Phase 2.2 : Created home dir with master key";
    261 
    262   creation_context_->mount_hash = mount_hash;
    263 
    264   // Plain text password, hashed and salted with individual salt.
    265   // It can be used for mounting homedir, and can be replaced only when signed.
    266   cryptohome::KeyDefinition password_key(
    267       creation_context_->salted_password,
    268       kCryptohomeSupervisedUserKeyLabel,
    269       kCryptohomeSupervisedUserKeyPrivileges);
    270   base::Base64Decode(creation_context_->encryption_key,
    271                      &password_key.encryption_key);
    272   base::Base64Decode(creation_context_->signature_key,
    273                      &password_key.signature_key);
    274 
    275   Key key(Key::KEY_TYPE_SALTED_PBKDF2_AES256_1234,
    276           std::string(),  // The salt is stored elsewhere.
    277           creation_context_->salted_master_key);
    278   key.SetLabel(kCryptohomeMasterKeyLabel);
    279   UserContext context(creation_context_->local_user_id);
    280   context.SetKey(key);
    281   context.SetIsUsingOAuth(false);
    282 
    283   authenticator_->AddKey(
    284       context,
    285       password_key,
    286       true,
    287       base::Bind(&ManagedUserCreationControllerNew::OnAddKeySuccess,
    288                  weak_factory_.GetWeakPtr()));
    289 }
    290 
    291 void ManagedUserCreationControllerNew::OnAddKeySuccess() {
    292   DCHECK(creation_context_);
    293   DCHECK_EQ(KEYS_GENERATED, stage_);
    294   stage_ = CRYPTOHOME_CREATED;
    295 
    296   VLOG(1) << " Phase 3 : Create/update user on chrome.com/manage";
    297 
    298   ProfileSyncService* sync_service =
    299       ProfileSyncServiceFactory::GetInstance()->GetForProfile(
    300           creation_context_->manager_profile);
    301   ProfileSyncService::SyncStatusSummary status =
    302       sync_service->QuerySyncStatusSummary();
    303 
    304   if (status == ProfileSyncService::DATATYPES_NOT_INITIALIZED)
    305     consumer_->OnLongCreationWarning();
    306 
    307   creation_context_->registration_utility =
    308       SupervisedUserRegistrationUtility::Create(
    309           creation_context_->manager_profile);
    310 
    311   SupervisedUserRegistrationInfo info(creation_context_->display_name,
    312                                       creation_context_->avatar_index);
    313   info.master_key = creation_context_->master_key;
    314   info.password_signature_key = creation_context_->signature_key;
    315   info.password_encryption_key = creation_context_->encryption_key;
    316 
    317   info.password_data.MergeDictionary(&creation_context_->password_data);
    318 
    319   // Registration utility will update user data if user already exist.
    320   creation_context_->registration_utility->Register(
    321       creation_context_->sync_user_id,
    322       info,
    323       base::Bind(&ManagedUserCreationControllerNew::RegistrationCallback,
    324                  weak_factory_.GetWeakPtr()));
    325 }
    326 
    327 void ManagedUserCreationControllerNew::RegistrationCallback(
    328     const GoogleServiceAuthError& error,
    329     const std::string& token) {
    330   DCHECK(creation_context_);
    331   DCHECK_EQ(CRYPTOHOME_CREATED, stage_);
    332 
    333   stage_ = DASHBOARD_CREATED;
    334 
    335   if (error.state() == GoogleServiceAuthError::NONE) {
    336     creation_context_->token = token;
    337 
    338     PostTaskAndReplyWithResult(
    339         content::BrowserThread::GetBlockingPool(),
    340         FROM_HERE,
    341         base::Bind(&StoreManagedUserFiles,
    342                    creation_context_->token,
    343                    MountManager::GetHomeDir(creation_context_->mount_hash)),
    344         base::Bind(&ManagedUserCreationControllerNew::OnManagedUserFilesStored,
    345                    weak_factory_.GetWeakPtr()));
    346   } else {
    347     stage_ = STAGE_ERROR;
    348     LOG(ERROR) << "Managed user creation failed. Error code " << error.state();
    349     if (consumer_)
    350       consumer_->OnCreationError(CLOUD_SERVER_ERROR);
    351   }
    352 }
    353 
    354 void ManagedUserCreationControllerNew::OnManagedUserFilesStored(bool success) {
    355   DCHECK(creation_context_);
    356   DCHECK_EQ(DASHBOARD_CREATED, stage_);
    357 
    358   if (!success) {
    359     stage_ = STAGE_ERROR;
    360     if (consumer_)
    361       consumer_->OnCreationError(TOKEN_WRITE_FAILED);
    362     return;
    363   }
    364   // Assume that new token is valid. It will be automatically invalidated if
    365   // sync service fails to use it.
    366   UserManager::Get()->SaveUserOAuthStatus(creation_context_->local_user_id,
    367                                           User::OAUTH2_TOKEN_STATUS_VALID);
    368 
    369   stage_ = TOKEN_WRITTEN;
    370 
    371   timeout_timer_.Stop();
    372   UserManager::Get()->GetSupervisedUserManager()->CommitCreationTransaction();
    373   content::RecordAction(
    374       base::UserMetricsAction("ManagedMode_LocallyManagedUserCreated"));
    375 
    376   stage_ = TRANSACTION_COMMITTED;
    377 
    378   if (consumer_)
    379     consumer_->OnCreationSuccess();
    380 }
    381 
    382 void ManagedUserCreationControllerNew::CreationTimedOut() {
    383   LOG(ERROR) << "Supervised user creation timed out. stage = " << stage_;
    384   if (consumer_)
    385     consumer_->OnCreationTimeout();
    386 }
    387 
    388 void ManagedUserCreationControllerNew::FinishCreation() {
    389   chrome::AttemptUserExit();
    390 }
    391 
    392 void ManagedUserCreationControllerNew::CancelCreation() {
    393   creation_context_->registration_utility.reset();
    394   chrome::AttemptUserExit();
    395 }
    396 
    397 std::string ManagedUserCreationControllerNew::GetManagedUserId() {
    398   DCHECK(creation_context_);
    399   return creation_context_->local_user_id;
    400 }
    401 
    402 }  // namespace chromeos
    403