Home | History | Annotate | Download | only in managed
      1 // Copyright (c) 2012 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/locally_managed_user_creation_controller.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/chromeos/chromeos_version.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/task_runner_util.h"
     14 #include "base/threading/sequenced_worker_pool.h"
     15 #include "base/values.h"
     16 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h"
     17 #include "chrome/browser/chromeos/login/mount_manager.h"
     18 #include "chrome/browser/chromeos/login/user.h"
     19 #include "chrome/browser/chromeos/login/user_manager.h"
     20 #include "chrome/browser/lifetime/application_lifetime.h"
     21 #include "chromeos/dbus/dbus_thread_manager.h"
     22 #include "chromeos/dbus/session_manager_client.h"
     23 #include "content/public/browser/browser_thread.h"
     24 #include "crypto/random.h"
     25 #include "google_apis/gaia/google_service_auth_error.h"
     26 
     27 namespace chromeos {
     28 
     29 namespace {
     30 
     31 const int kMasterKeySize = 32;
     32 const int kUserCreationTimeoutSeconds = 60; // 60 seconds.
     33 
     34 bool StoreManagedUserFiles(const std::string& token,
     35                            const base::FilePath& base_path) {
     36   if (!base::chromeos::IsRunningOnChromeOS()) {
     37     // If running on desktop, cryptohome stub does not create home directory.
     38     file_util::CreateDirectory(base_path);
     39   }
     40   base::FilePath token_file = base_path.Append(kManagedUserTokenFilename);
     41   int bytes = file_util::WriteFile(token_file, token.c_str(), token.length());
     42   return bytes >= 0;
     43 }
     44 
     45 } // namespace
     46 
     47 LocallyManagedUserCreationController::StatusConsumer::~StatusConsumer() {}
     48 
     49 LocallyManagedUserCreationController::UserCreationContext::UserCreationContext()
     50     : token_acquired(false),
     51       token_succesfully_written(false),
     52       manager_profile(NULL) {}
     53 
     54 LocallyManagedUserCreationController::UserCreationContext::
     55     ~UserCreationContext() {}
     56 
     57 // static
     58 LocallyManagedUserCreationController*
     59     LocallyManagedUserCreationController::current_controller_ = NULL;
     60 
     61 LocallyManagedUserCreationController::LocallyManagedUserCreationController(
     62     LocallyManagedUserCreationController::StatusConsumer* consumer,
     63     const std::string& manager_id)
     64     : consumer_(consumer),
     65       weak_factory_(this) {
     66   DCHECK(!current_controller_) << "More than one controller exist.";
     67   current_controller_ = this;
     68   creation_context_.reset(
     69       new LocallyManagedUserCreationController::UserCreationContext());
     70   creation_context_->manager_id = manager_id;
     71 }
     72 
     73 LocallyManagedUserCreationController::~LocallyManagedUserCreationController() {
     74   current_controller_ = NULL;
     75 }
     76 
     77 void LocallyManagedUserCreationController::SetUpCreation(string16 display_name,
     78                                                          std::string password) {
     79   DCHECK(creation_context_);
     80   creation_context_->display_name = display_name;
     81   creation_context_->password = password;
     82 }
     83 
     84 void LocallyManagedUserCreationController::SetManagerProfile(
     85     Profile* manager_profile) {
     86   creation_context_->manager_profile = manager_profile;
     87 }
     88 
     89 void LocallyManagedUserCreationController::StartCreation() {
     90   DCHECK(creation_context_);
     91   VLOG(1) << "Starting supervised user creation";
     92   timeout_timer_.Start(
     93       FROM_HERE, base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds),
     94       this,
     95       &LocallyManagedUserCreationController::CreationTimedOut);
     96 
     97   UserManager::Get()->StartLocallyManagedUserCreationTransaction(
     98       creation_context_->display_name);
     99 
    100   creation_context_->local_user_id =
    101         UserManager::Get()->GenerateUniqueLocallyManagedUserId();
    102   creation_context_->sync_user_id =
    103       ManagedUserRegistrationUtility::GenerateNewManagedUserId();
    104 
    105   UserManager::Get()->CreateLocallyManagedUserRecord(
    106       creation_context_->manager_id,
    107       creation_context_->local_user_id,
    108       creation_context_->sync_user_id,
    109       creation_context_->display_name);
    110 
    111   UserManager::Get()->SetLocallyManagedUserCreationTransactionUserId(
    112       creation_context_->local_user_id);
    113   VLOG(1) << "Creating cryptohome";
    114   authenticator_ = new ManagedUserAuthenticator(this);
    115   authenticator_->AuthenticateToCreate(creation_context_->local_user_id,
    116                                        creation_context_->password);
    117 }
    118 
    119 void LocallyManagedUserCreationController::OnAuthenticationFailure(
    120     ManagedUserAuthenticator::AuthState error) {
    121   timeout_timer_.Stop();
    122   ErrorCode code = NO_ERROR;
    123   switch (error) {
    124     case ManagedUserAuthenticator::NO_MOUNT:
    125       code = CRYPTOHOME_NO_MOUNT;
    126       break;
    127     case ManagedUserAuthenticator::FAILED_MOUNT:
    128       code = CRYPTOHOME_FAILED_MOUNT;
    129       break;
    130     case ManagedUserAuthenticator::FAILED_TPM:
    131       code = CRYPTOHOME_FAILED_TPM;
    132       break;
    133     default:
    134       NOTREACHED();
    135   }
    136   if (consumer_)
    137     consumer_->OnCreationError(code);
    138 }
    139 
    140 void LocallyManagedUserCreationController::OnMountSuccess(
    141     const std::string& mount_hash) {
    142   creation_context_->mount_hash = mount_hash;
    143 
    144   // Generate master password.
    145   char master_key_bytes[kMasterKeySize];
    146   crypto::RandBytes(&master_key_bytes, sizeof(master_key_bytes));
    147   creation_context_->master_key = StringToLowerASCII(base::HexEncode(
    148       reinterpret_cast<const void*>(master_key_bytes),
    149       sizeof(master_key_bytes)));
    150   VLOG(1) << "Adding master key";
    151   authenticator_->AddMasterKey(creation_context_->local_user_id,
    152                                creation_context_->password,
    153                                creation_context_->master_key);
    154 }
    155 
    156 void LocallyManagedUserCreationController::OnAddKeySuccess() {
    157   creation_context_->registration_utility =
    158       ManagedUserRegistrationUtility::Create(
    159           creation_context_->manager_profile);
    160 
    161   VLOG(1) << "Creating user on server";
    162   ManagedUserRegistrationInfo info(creation_context_->display_name);
    163   info.master_key = creation_context_->master_key;
    164   creation_context_->registration_utility->Register(
    165       creation_context_->sync_user_id,
    166       info,
    167       base::Bind(&LocallyManagedUserCreationController::RegistrationCallback,
    168                  weak_factory_.GetWeakPtr()));
    169 }
    170 
    171 void LocallyManagedUserCreationController::RegistrationCallback(
    172     const GoogleServiceAuthError& error,
    173     const std::string& token) {
    174   if (error.state() == GoogleServiceAuthError::NONE) {
    175     TokenFetched(token);
    176   } else {
    177     timeout_timer_.Stop();
    178     LOG(ERROR) << "Managed user creation failed. Error code " << error.state();
    179     if (consumer_)
    180       consumer_->OnCreationError(CLOUD_SERVER_ERROR);
    181   }
    182 }
    183 
    184 void LocallyManagedUserCreationController::CreationTimedOut() {
    185   LOG(ERROR) << "Supervised user creation timed out.";
    186   if (consumer_)
    187     consumer_->OnCreationTimeout();
    188 }
    189 
    190 void LocallyManagedUserCreationController::FinishCreation() {
    191   chrome::AttemptUserExit();
    192 }
    193 
    194 void LocallyManagedUserCreationController::CancelCreation() {
    195   creation_context_->registration_utility.reset();
    196   chrome::AttemptUserExit();
    197 }
    198 
    199 std::string LocallyManagedUserCreationController::GetManagedUserId() {
    200   DCHECK(creation_context_);
    201   return creation_context_->local_user_id;
    202 }
    203 
    204 void LocallyManagedUserCreationController::TokenFetched(
    205     const std::string& token) {
    206   creation_context_->token_acquired = true;
    207   creation_context_->token = token;
    208 
    209   PostTaskAndReplyWithResult(
    210       content::BrowserThread::GetBlockingPool(),
    211       FROM_HERE,
    212       base::Bind(&StoreManagedUserFiles,
    213                  creation_context_->token,
    214                  MountManager::GetHomeDir(creation_context_->mount_hash)),
    215       base::Bind(
    216            &LocallyManagedUserCreationController::OnManagedUserFilesStored,
    217            weak_factory_.GetWeakPtr()));
    218 }
    219 
    220 void LocallyManagedUserCreationController::OnManagedUserFilesStored(
    221     bool success) {
    222   timeout_timer_.Stop();
    223   if (!success) {
    224     if (consumer_)
    225       consumer_->OnCreationError(TOKEN_WRITE_FAILED);
    226     return;
    227   }
    228   // Assume that new token is valid. It will be automatically invalidated if
    229   // sync service fails to use it.
    230   UserManager::Get()->SaveUserOAuthStatus(creation_context_->local_user_id,
    231                                           User::OAUTH2_TOKEN_STATUS_VALID);
    232   UserManager::Get()->CommitLocallyManagedUserCreationTransaction();
    233   if (consumer_)
    234     consumer_->OnCreationSuccess();
    235 }
    236 
    237 }  // namespace chromeos
    238