Turn UserContext into a class with explicit getters and setters
[chromium-blink-merge.git] / chrome / browser / chromeos / login / managed / supervised_user_login_flow.cc
blob5bad1173f958ed6d2ac8855824aed6254ea7ee7f
1 // Copyright 2013 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.
5 #include "chrome/browser/chromeos/login/managed/supervised_user_login_flow.h"
7 #include "base/base64.h"
8 #include "base/logging.h"
9 #include "base/metrics/histogram.h"
10 #include "base/prefs/pref_registry_simple.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/values.h"
13 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
14 #include "chrome/browser/chromeos/login/login_utils.h"
15 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h"
16 #include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h"
17 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h"
18 #include "chrome/browser/chromeos/login/supervised_user_manager.h"
19 #include "chrome/browser/chromeos/login/user_manager.h"
20 #include "chrome/browser/chromeos/login/wizard_controller.h"
21 #include "content/public/browser/browser_thread.h"
23 using content::BrowserThread;
25 namespace chromeos {
27 SupervisedUserLoginFlow::SupervisedUserLoginFlow(
28 const std::string& user_id)
29 : ExtendedUserFlow(user_id),
30 data_loaded_(false),
31 weak_factory_(this) {
34 SupervisedUserLoginFlow::~SupervisedUserLoginFlow() {}
36 bool SupervisedUserLoginFlow::CanLockScreen() {
37 return true;
40 bool SupervisedUserLoginFlow::ShouldLaunchBrowser() {
41 return data_loaded_;
44 bool SupervisedUserLoginFlow::ShouldSkipPostLoginScreens() {
45 return true;
48 bool SupervisedUserLoginFlow::HandleLoginFailure(
49 const LoginFailure& failure) {
50 return false;
53 bool SupervisedUserLoginFlow::HandlePasswordChangeDetected() {
54 return false;
57 void SupervisedUserLoginFlow::HandleOAuthTokenStatusChange(
58 User::OAuthTokenStatus status) {
61 void SupervisedUserLoginFlow::OnSyncSetupDataLoaded(
62 const std::string& token) {
63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
64 ConfigureSync(token);
67 void SupervisedUserLoginFlow::ConfigureSync(const std::string& token) {
68 data_loaded_ = true;
70 // TODO(antrim): add error handling (no token loaded).
71 // See also: http://crbug.com/312751
72 UserManager::Get()->GetSupervisedUserManager()->ConfigureSyncWithToken(
73 profile_, token);
74 SupervisedUserAuthentication* auth =
75 UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
77 if (auth->HasScheduledPasswordUpdate(user_id())) {
78 auth->LoadPasswordUpdateData(
79 user_id(),
80 base::Bind(&SupervisedUserLoginFlow::OnPasswordChangeDataLoaded,
81 weak_factory_.GetWeakPtr()),
82 base::Bind(&SupervisedUserLoginFlow::OnPasswordChangeDataLoadFailed,
83 weak_factory_.GetWeakPtr()));
84 return;
86 Finish();
89 void SupervisedUserLoginFlow::HandleLoginSuccess(
90 const UserContext& login_context) {
91 context_.CopyFrom(login_context);
94 void SupervisedUserLoginFlow::OnPasswordChangeDataLoaded(
95 const base::DictionaryValue* password_data) {
96 // Edge case, when manager has signed in and already updated the password.
97 SupervisedUserAuthentication* auth =
98 UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
99 if (!auth->NeedPasswordChange(user_id(), password_data)) {
100 VLOG(1) << "Password already changed for " << user_id();
101 auth->ClearScheduledPasswordUpdate(user_id());
102 Finish();
103 return;
106 // Two cases now - we can currently have either old-style password, or new
107 // password.
108 std::string base64_signature;
109 std::string signature;
110 std::string password;
111 int revision = 0;
112 int schema = 0;
113 bool success = password_data->GetStringWithoutPathExpansion(
114 kPasswordSignature, &base64_signature);
115 success &= password_data->GetIntegerWithoutPathExpansion(kPasswordRevision,
116 &revision);
117 success &=
118 password_data->GetIntegerWithoutPathExpansion(kSchemaVersion, &schema);
119 success &= password_data->GetStringWithoutPathExpansion(kEncryptedPassword,
120 &password);
121 if (!success) {
122 LOG(ERROR) << "Incomplete data for password change";
124 UMA_HISTOGRAM_ENUMERATION(
125 "ManagedUsers.ChromeOS.PasswordChange",
126 SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_INCOMPLETE_DATA,
127 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
128 Finish();
129 return;
131 base::Base64Decode(base64_signature, &signature);
132 scoped_ptr<base::DictionaryValue> data_copy(password_data->DeepCopy());
133 cryptohome::KeyDefinition key(password,
134 kCryptohomeManagedUserKeyLabel,
135 kCryptohomeManagedUserKeyPrivileges);
137 authenticator_ = new ExtendedAuthenticator(this);
138 SupervisedUserAuthentication::Schema current_schema =
139 auth->GetPasswordSchema(user_id());
141 key.revision = revision;
143 if (SupervisedUserAuthentication::SCHEMA_PLAIN == current_schema) {
144 // We need to add new key, and block old one. As we don't actually have
145 // signature key, use Migrate privilege instead of AuthorizedUpdate.
146 key.privileges = kCryptohomeManagedUserIncompleteKeyPrivileges;
148 VLOG(1) << "Adding new schema key";
149 DCHECK(context_.GetKeyLabel().empty());
150 authenticator_->AddKey(context_,
151 key,
152 false /* no key exists */,
153 base::Bind(&SupervisedUserLoginFlow::OnNewKeyAdded,
154 weak_factory_.GetWeakPtr(),
155 Passed(&data_copy)));
156 } else if (SupervisedUserAuthentication::SCHEMA_SALT_HASHED ==
157 current_schema) {
158 VLOG(1) << "Updating the key";
160 if (auth->HasIncompleteKey(user_id())) {
161 // We need to use Migrate instead of Authorized Update privilege.
162 key.privileges = kCryptohomeManagedUserIncompleteKeyPrivileges;
164 // Just update the key.
165 DCHECK_EQ(context_.GetKeyLabel(), kCryptohomeManagedUserKeyLabel);
166 authenticator_->UpdateKeyAuthorized(
167 context_,
168 key,
169 signature,
170 base::Bind(&SupervisedUserLoginFlow::OnPasswordUpdated,
171 weak_factory_.GetWeakPtr(),
172 Passed(&data_copy)));
173 } else {
174 NOTREACHED() << "Unsupported password schema";
178 void SupervisedUserLoginFlow::OnNewKeyAdded(
179 scoped_ptr<base::DictionaryValue> password_data) {
180 VLOG(1) << "New key added";
181 SupervisedUserAuthentication* auth =
182 UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
183 auth->StorePasswordData(user_id(), *password_data.get());
184 auth->MarkKeyIncomplete(user_id(), true /* incomplete */);
185 authenticator_->RemoveKey(
186 context_,
187 kLegacyCryptohomeManagedUserKeyLabel,
188 base::Bind(&SupervisedUserLoginFlow::OnOldKeyRemoved,
189 weak_factory_.GetWeakPtr()));
192 void SupervisedUserLoginFlow::OnOldKeyRemoved() {
193 UMA_HISTOGRAM_ENUMERATION(
194 "ManagedUsers.ChromeOS.PasswordChange",
195 SupervisedUserAuthentication::PASSWORD_CHANGED_IN_USER_SESSION,
196 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
197 Finish();
200 void SupervisedUserLoginFlow::OnPasswordChangeDataLoadFailed() {
201 LOG(ERROR) << "Could not load data for password change";
203 UMA_HISTOGRAM_ENUMERATION(
204 "ManagedUsers.ChromeOS.PasswordChange",
205 SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_LOADING_DATA,
206 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
207 Finish();
210 void SupervisedUserLoginFlow::OnAuthenticationFailure(
211 ExtendedAuthenticator::AuthState state) {
212 LOG(ERROR) << "Authentication error during password change";
214 UMA_HISTOGRAM_ENUMERATION(
215 "ManagedUsers.ChromeOS.PasswordChange",
216 SupervisedUserAuthentication::
217 PASSWORD_CHANGE_FAILED_AUTHENTICATION_FAILURE,
218 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
219 Finish();
222 void SupervisedUserLoginFlow::OnPasswordUpdated(
223 scoped_ptr<base::DictionaryValue> password_data) {
224 VLOG(1) << "Updated password for supervised user";
226 SupervisedUserAuthentication* auth =
227 UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
229 // Incomplete state is not there in password_data, carry it from old state.
230 bool was_incomplete = auth->HasIncompleteKey(user_id());
231 auth->StorePasswordData(user_id(), *password_data.get());
232 if (was_incomplete)
233 auth->MarkKeyIncomplete(user_id(), true /* incomplete */);
235 UMA_HISTOGRAM_ENUMERATION(
236 "ManagedUsers.ChromeOS.PasswordChange",
237 SupervisedUserAuthentication::PASSWORD_CHANGED_IN_USER_SESSION,
238 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
239 Finish();
242 void SupervisedUserLoginFlow::Finish() {
243 LoginUtils::Get()->DoBrowserLaunch(profile_, host());
244 profile_ = NULL;
245 UnregisterFlowSoon();
248 void SupervisedUserLoginFlow::LaunchExtraSteps(
249 Profile* profile) {
250 profile_ = profile;
251 UserManager::Get()->GetSupervisedUserManager()->LoadSupervisedUserToken(
252 profile,
253 base::Bind(
254 &SupervisedUserLoginFlow::OnSyncSetupDataLoaded,
255 weak_factory_.GetWeakPtr()));
258 } // namespace chromeos