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/file_util.h"
      9 #include "base/files/file_path.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "base/strings/string_util.h"
     12 #include "base/sys_info.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/supervised_user_manager.h"
     19 #include "chrome/browser/chromeos/login/user.h"
     20 #include "chrome/browser/chromeos/login/user_manager.h"
     21 #include "chrome/browser/lifetime/application_lifetime.h"
     22 #include "chrome/browser/sync/profile_sync_service.h"
     23 #include "chrome/browser/sync/profile_sync_service_factory.h"
     24 #include "chromeos/dbus/dbus_thread_manager.h"
     25 #include "chromeos/dbus/session_manager_client.h"
     26 #include "content/public/browser/browser_thread.h"
     27 #include "content/public/browser/user_metrics.h"
     28 #include "crypto/random.h"
     29 #include "google_apis/gaia/google_service_auth_error.h"
     30 
     31 namespace chromeos {
     32 
     33 namespace {
     34 
     35 const int kMasterKeySize = 32;
     36 const int kUserCreationTimeoutSeconds = 30; // 30 seconds.
     37 
     38 bool StoreManagedUserFiles(const std::string& token,
     39                            const base::FilePath& base_path) {
     40   if (!base::SysInfo::IsRunningOnChromeOS()) {
     41     // If running on desktop, cryptohome stub does not create home directory.
     42     base::CreateDirectory(base_path);
     43   }
     44   base::FilePath token_file = base_path.Append(kManagedUserTokenFilename);
     45   int bytes = file_util::WriteFile(token_file, token.c_str(), token.length());
     46   return bytes >= 0;
     47 }
     48 
     49 } // namespace
     50 
     51 // static
     52 const int LocallyManagedUserCreationController::kDummyAvatarIndex = -111;
     53 
     54 LocallyManagedUserCreationController::StatusConsumer::~StatusConsumer() {}
     55 
     56 LocallyManagedUserCreationController::UserCreationContext::UserCreationContext()
     57     : avatar_index(kDummyAvatarIndex),
     58       token_acquired(false),
     59       token_succesfully_written(false),
     60       creation_type(NEW_USER),
     61       manager_profile(NULL) {}
     62 
     63 LocallyManagedUserCreationController::UserCreationContext::
     64     ~UserCreationContext() {}
     65 
     66 // static
     67 LocallyManagedUserCreationController*
     68     LocallyManagedUserCreationController::current_controller_ = NULL;
     69 
     70 LocallyManagedUserCreationController::LocallyManagedUserCreationController(
     71     LocallyManagedUserCreationController::StatusConsumer* consumer,
     72     const std::string& manager_id)
     73     : consumer_(consumer),
     74       weak_factory_(this) {
     75   DCHECK(!current_controller_) << "More than one controller exist.";
     76   current_controller_ = this;
     77   creation_context_.reset(
     78       new LocallyManagedUserCreationController::UserCreationContext());
     79   creation_context_->manager_id = manager_id;
     80 }
     81 
     82 LocallyManagedUserCreationController::~LocallyManagedUserCreationController() {
     83   current_controller_ = NULL;
     84 }
     85 
     86 void LocallyManagedUserCreationController::SetUpCreation(
     87     const base::string16& display_name,
     88     const std::string& password,
     89     int avatar_index) {
     90   DCHECK(creation_context_);
     91   creation_context_->display_name = display_name;
     92   creation_context_->password = password;
     93   creation_context_->avatar_index = avatar_index;
     94 }
     95 
     96 void LocallyManagedUserCreationController::StartImport(
     97     const base::string16& display_name,
     98     const std::string& password,
     99     int avatar_index,
    100     const std::string& sync_id,
    101     const std::string& master_key) {
    102   DCHECK(creation_context_);
    103   creation_context_->creation_type = USER_IMPORT;
    104   creation_context_->display_name = display_name;
    105   creation_context_->password = password;
    106   creation_context_->avatar_index = avatar_index;
    107   creation_context_->sync_user_id = sync_id;
    108   creation_context_->master_key = master_key;
    109   StartCreation();
    110 }
    111 
    112 void LocallyManagedUserCreationController::SetManagerProfile(
    113     Profile* manager_profile) {
    114   creation_context_->manager_profile = manager_profile;
    115 }
    116 
    117 void LocallyManagedUserCreationController::StartCreation() {
    118   DCHECK(creation_context_);
    119   VLOG(1) << "Starting supervised user creation";
    120 
    121   ProfileSyncService* sync_service =
    122       ProfileSyncServiceFactory::GetInstance()->GetForProfile(
    123           creation_context_->manager_profile);
    124   ProfileSyncService::SyncStatusSummary status =
    125       sync_service->QuerySyncStatusSummary();
    126 
    127   if (status == ProfileSyncService::DATATYPES_NOT_INITIALIZED)
    128     consumer_->OnLongCreationWarning();
    129 
    130   timeout_timer_.Start(
    131       FROM_HERE, base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds),
    132       this,
    133       &LocallyManagedUserCreationController::CreationTimedOut);
    134   SupervisedUserManager* manager =
    135       UserManager::Get()->GetSupervisedUserManager();
    136   manager->StartCreationTransaction(creation_context_->display_name);
    137 
    138   creation_context_->local_user_id = manager->GenerateUserId();
    139 
    140   if (creation_context_->creation_type == NEW_USER) {
    141     creation_context_->sync_user_id =
    142         ManagedUserRegistrationUtility::GenerateNewManagedUserId();
    143   }
    144 
    145   manager->CreateUserRecord(
    146       creation_context_->manager_id,
    147       creation_context_->local_user_id,
    148       creation_context_->sync_user_id,
    149       creation_context_->display_name);
    150 
    151   manager->SetCreationTransactionUserId(creation_context_->local_user_id);
    152   VLOG(1) << "Creating cryptohome";
    153   authenticator_ = new ManagedUserAuthenticator(this);
    154   authenticator_->AuthenticateToCreate(creation_context_->local_user_id,
    155                                        creation_context_->password);
    156 }
    157 
    158 void LocallyManagedUserCreationController::OnAuthenticationFailure(
    159     ManagedUserAuthenticator::AuthState error) {
    160   timeout_timer_.Stop();
    161   ErrorCode code = NO_ERROR;
    162   switch (error) {
    163     case ManagedUserAuthenticator::NO_MOUNT:
    164       code = CRYPTOHOME_NO_MOUNT;
    165       break;
    166     case ManagedUserAuthenticator::FAILED_MOUNT:
    167       code = CRYPTOHOME_FAILED_MOUNT;
    168       break;
    169     case ManagedUserAuthenticator::FAILED_TPM:
    170       code = CRYPTOHOME_FAILED_TPM;
    171       break;
    172     default:
    173       NOTREACHED();
    174   }
    175   if (consumer_)
    176     consumer_->OnCreationError(code);
    177 }
    178 
    179 void LocallyManagedUserCreationController::OnMountSuccess(
    180     const std::string& mount_hash) {
    181   creation_context_->mount_hash = mount_hash;
    182 
    183   if (creation_context_->creation_type == NEW_USER) {
    184     // Generate master password.
    185     char master_key_bytes[kMasterKeySize];
    186     crypto::RandBytes(&master_key_bytes, sizeof(master_key_bytes));
    187     creation_context_->master_key = StringToLowerASCII(base::HexEncode(
    188         reinterpret_cast<const void*>(master_key_bytes),
    189         sizeof(master_key_bytes)));
    190   }
    191 
    192   VLOG(1) << "Adding master key";
    193   authenticator_->AddMasterKey(creation_context_->local_user_id,
    194                                creation_context_->password,
    195                                creation_context_->master_key);
    196 }
    197 
    198 void LocallyManagedUserCreationController::OnAddKeySuccess() {
    199   creation_context_->registration_utility =
    200       ManagedUserRegistrationUtility::Create(
    201           creation_context_->manager_profile);
    202 
    203   VLOG(1) << "Creating user on server";
    204   ManagedUserRegistrationInfo info(creation_context_->display_name,
    205                                    creation_context_->avatar_index);
    206   info.master_key = creation_context_->master_key;
    207   timeout_timer_.Stop();
    208   creation_context_->registration_utility->Register(
    209       creation_context_->sync_user_id,
    210       info,
    211       base::Bind(&LocallyManagedUserCreationController::RegistrationCallback,
    212                  weak_factory_.GetWeakPtr()));
    213 }
    214 
    215 void LocallyManagedUserCreationController::RegistrationCallback(
    216     const GoogleServiceAuthError& error,
    217     const std::string& token) {
    218   if (error.state() == GoogleServiceAuthError::NONE) {
    219     timeout_timer_.Start(
    220         FROM_HERE, base::TimeDelta::FromSeconds(kUserCreationTimeoutSeconds),
    221         this,
    222         &LocallyManagedUserCreationController::CreationTimedOut);
    223     TokenFetched(token);
    224   } else {
    225     LOG(ERROR) << "Managed user creation failed. Error code " << error.state();
    226     if (consumer_)
    227       consumer_->OnCreationError(CLOUD_SERVER_ERROR);
    228   }
    229 }
    230 
    231 void LocallyManagedUserCreationController::CreationTimedOut() {
    232   LOG(ERROR) << "Supervised user creation timed out.";
    233   if (consumer_)
    234     consumer_->OnCreationTimeout();
    235 }
    236 
    237 void LocallyManagedUserCreationController::FinishCreation() {
    238   chrome::AttemptUserExit();
    239 }
    240 
    241 void LocallyManagedUserCreationController::CancelCreation() {
    242   creation_context_->registration_utility.reset();
    243   chrome::AttemptUserExit();
    244 }
    245 
    246 std::string LocallyManagedUserCreationController::GetManagedUserId() {
    247   DCHECK(creation_context_);
    248   return creation_context_->local_user_id;
    249 }
    250 
    251 void LocallyManagedUserCreationController::TokenFetched(
    252     const std::string& token) {
    253   creation_context_->token_acquired = true;
    254   creation_context_->token = token;
    255 
    256   PostTaskAndReplyWithResult(
    257       content::BrowserThread::GetBlockingPool(),
    258       FROM_HERE,
    259       base::Bind(&StoreManagedUserFiles,
    260                  creation_context_->token,
    261                  MountManager::GetHomeDir(creation_context_->mount_hash)),
    262       base::Bind(
    263            &LocallyManagedUserCreationController::OnManagedUserFilesStored,
    264            weak_factory_.GetWeakPtr()));
    265 }
    266 
    267 void LocallyManagedUserCreationController::OnManagedUserFilesStored(
    268     bool success) {
    269   timeout_timer_.Stop();
    270 
    271   content::RecordAction(
    272       content::UserMetricsAction("ManagedMode_LocallyManagedUserCreated"));
    273 
    274   if (!success) {
    275     if (consumer_)
    276       consumer_->OnCreationError(TOKEN_WRITE_FAILED);
    277     return;
    278   }
    279   // Assume that new token is valid. It will be automatically invalidated if
    280   // sync service fails to use it.
    281   UserManager::Get()->SaveUserOAuthStatus(creation_context_->local_user_id,
    282                                           User::OAUTH2_TOKEN_STATUS_VALID);
    283   UserManager::Get()->GetSupervisedUserManager()->
    284       CommitCreationTransaction();
    285   if (consumer_)
    286     consumer_->OnCreationSuccess();
    287 }
    288 
    289 }  // namespace chromeos
    290