File: lock_to_single_user_manager.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (175 lines) | stat: -rw-r--r-- 6,133 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/policy/handlers/lock_to_single_user_manager.h"

#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "chrome/browser/ash/crostini/crostini_manager.h"
#include "chrome/browser/ash/plugin_vm/plugin_vm_manager.h"
#include "chrome/browser/ash/plugin_vm/plugin_vm_manager_factory.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chromeos/ash/components/cryptohome/cryptohome_parameters.h"
#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
#include "chromeos/ash/components/login/session/session_termination_manager.h"
#include "chromeos/ash/components/settings/cros_settings.h"
#include "chromeos/ash/components/settings/cros_settings_names.h"
#include "components/policy/proto/chrome_device_policy.pb.h"

using RebootOnSignOutPolicy =
    enterprise_management::DeviceRebootOnUserSignoutProto;
using RebootOnSignOutRequest =
    user_data_auth::LockToSingleUserMountUntilRebootRequest;
using RebootOnSignOutReply =
    user_data_auth::LockToSingleUserMountUntilRebootReply;

namespace policy {

namespace {

ash::ConciergeClient* GetConciergeClient() {
  return ash::ConciergeClient::Get();
}

LockToSingleUserManager* g_lock_to_single_user_manager_instance;
}  // namespace

// static
LockToSingleUserManager*
LockToSingleUserManager::GetLockToSingleUserManagerInstance() {
  return g_lock_to_single_user_manager_instance;
}

LockToSingleUserManager::LockToSingleUserManager() {
  user_manager::UserManager::Get()->AddSessionStateObserver(this);

  DCHECK(!g_lock_to_single_user_manager_instance);
  g_lock_to_single_user_manager_instance = this;
}

LockToSingleUserManager::~LockToSingleUserManager() {
  user_manager::UserManager::Get()->RemoveSessionStateObserver(this);

  g_lock_to_single_user_manager_instance = nullptr;
}

void LockToSingleUserManager::DbusNotifyVmStarting() {
  if (lock_to_single_user_on_dbus_call_)
    LockToSingleUser();
}

void LockToSingleUserManager::ActiveUserChanged(user_manager::User* user) {
  user->IsAffiliatedAsync(
      base::BindOnce(&LockToSingleUserManager::OnUserAffiliationEstablished,
                     weak_factory_.GetWeakPtr(), user));
}

void LockToSingleUserManager::OnUserAffiliationEstablished(
    user_manager::User* user,
    bool is_affiliated) {
  if (is_affiliated)
    return;

  int policy_value = -1;
  if (!ash::CrosSettings::Get()->GetInteger(ash::kDeviceRebootOnUserSignout,
                                            &policy_value)) {
    return;
  }

  user_manager::UserManager::Get()->RemoveSessionStateObserver(this);
  switch (policy_value) {
    default:
    case RebootOnSignOutPolicy::ALWAYS:
      user->AddProfileCreatedObserver(
          base::BindOnce(&LockToSingleUserManager::LockToSingleUser,
                         weak_factory_.GetWeakPtr()));
      break;
    case RebootOnSignOutPolicy::VM_STARTED_OR_ARC_SESSION:
      user->AddProfileCreatedObserver(
          base::BindOnce(&LockToSingleUserManager::AddVmStartingObservers,
                         weak_factory_.GetWeakPtr(), user));
      arc_session_observation_.Observe(arc::ArcSessionManager::Get());
      break;
    case RebootOnSignOutPolicy::ARC_SESSION:
      arc_session_observation_.Observe(arc::ArcSessionManager::Get());
      break;
    case RebootOnSignOutPolicy::NEVER:
      break;
  }
}

void LockToSingleUserManager::OnArcStarted() {
  arc_session_observation_.Reset();
  LockToSingleUser();
}

void LockToSingleUserManager::OnVmStarted(
    const vm_tools::concierge::VmStartedSignal& signal) {
  // When we receive the VmStarted signal we expect to already be locked to a
  // single user.

  GetConciergeClient()->RemoveVmObserver(this);
  LockToSingleUser();
  expect_to_be_locked_ = true;
}

void LockToSingleUserManager::OnVmStopped(
    const vm_tools::concierge::VmStoppedSignal& signal) {}

void LockToSingleUserManager::OnVmStarting() {
  LockToSingleUser();
}

void LockToSingleUserManager::AddVmStartingObservers(user_manager::User* user) {
  Profile* profile = ash::ProfileHelper::Get()->GetProfileByUser(user);

  crostini::CrostiniManager::GetForProfile(profile)->AddVmStartingObserver(
      this);
  plugin_vm::PluginVmManagerFactory::GetForProfile(profile)
      ->AddVmStartingObserver(this);

  GetConciergeClient()->AddVmObserver(this);

  lock_to_single_user_on_dbus_call_ = true;
}

void LockToSingleUserManager::LockToSingleUser() {
  cryptohome::AccountIdentifier account_id =
      cryptohome::CreateAccountIdentifierFromAccountId(
          user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId());
  RebootOnSignOutRequest request;
  request.mutable_account_id()->CopyFrom(account_id);
  ash::CryptohomeMiscClient::Get()->LockToSingleUserMountUntilReboot(
      request,
      base::BindOnce(
          &LockToSingleUserManager::OnLockToSingleUserMountUntilRebootDone,
          weak_factory_.GetWeakPtr()));
}

void LockToSingleUserManager::OnLockToSingleUserMountUntilRebootDone(
    std::optional<RebootOnSignOutReply> reply) {
  if (!reply.has_value()) {
    LOG(ERROR) << "Signing out user: no reply from "
                  "LockToSingleUserMountUntilReboot D-Bus call.";
    chrome::AttemptUserExit();
    return;
  }

  // Force user logout if failed to lock the device to single user mount.
  if (reply->error() ==
          user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_NOT_SET ||
      reply->error() == user_data_auth::CRYPTOHOME_ERROR_PCR_ALREADY_EXTENDED) {
    // The device is locked to single user on TPM level. Update the cache in
    // SessionTerminationManager, so that it triggers reboot on sign out.
    ash::SessionTerminationManager::Get()->SetDeviceLockedToSingleUser();
  } else {
    LOG(ERROR) << "Signing out user: failed to lock device to single user: "
               << reply->error();
    chrome::AttemptUserExit();
  }
}

}  // namespace policy