OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chrome/browser/chromeos/login/managed/supervised_user_login_flow.h" | |
6 | |
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_utils.h" | |
14 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h
" | |
15 #include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_sc
reen.h" | |
16 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h
" | |
17 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" | |
18 #include "chrome/browser/chromeos/login/users/supervised_user_manager.h" | |
19 #include "chrome/browser/chromeos/login/users/user_manager.h" | |
20 #include "chrome/browser/chromeos/login/wizard_controller.h" | |
21 #include "chromeos/login/auth/key.h" | |
22 #include "content/public/browser/browser_thread.h" | |
23 | |
24 using content::BrowserThread; | |
25 | |
26 namespace chromeos { | |
27 | |
28 SupervisedUserLoginFlow::SupervisedUserLoginFlow( | |
29 const std::string& user_id) | |
30 : ExtendedUserFlow(user_id), | |
31 data_loaded_(false), | |
32 weak_factory_(this) { | |
33 } | |
34 | |
35 SupervisedUserLoginFlow::~SupervisedUserLoginFlow() {} | |
36 | |
37 bool SupervisedUserLoginFlow::CanLockScreen() { | |
38 return true; | |
39 } | |
40 | |
41 bool SupervisedUserLoginFlow::ShouldLaunchBrowser() { | |
42 return data_loaded_; | |
43 } | |
44 | |
45 bool SupervisedUserLoginFlow::ShouldSkipPostLoginScreens() { | |
46 return true; | |
47 } | |
48 | |
49 bool SupervisedUserLoginFlow::HandleLoginFailure(const AuthFailure& failure) { | |
50 return false; | |
51 } | |
52 | |
53 bool SupervisedUserLoginFlow::HandlePasswordChangeDetected() { | |
54 return false; | |
55 } | |
56 | |
57 void SupervisedUserLoginFlow::HandleOAuthTokenStatusChange( | |
58 User::OAuthTokenStatus status) { | |
59 } | |
60 | |
61 void SupervisedUserLoginFlow::OnSyncSetupDataLoaded( | |
62 const std::string& token) { | |
63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
64 ConfigureSync(token); | |
65 } | |
66 | |
67 void SupervisedUserLoginFlow::ConfigureSync(const std::string& token) { | |
68 data_loaded_ = true; | |
69 | |
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(); | |
76 | |
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; | |
85 } | |
86 Finish(); | |
87 } | |
88 | |
89 void SupervisedUserLoginFlow::HandleLoginSuccess( | |
90 const UserContext& login_context) { | |
91 context_ = login_context; | |
92 } | |
93 | |
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; | |
104 } | |
105 | |
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"; | |
123 | |
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; | |
130 } | |
131 base::Base64Decode(base64_signature, &signature); | |
132 scoped_ptr<base::DictionaryValue> data_copy(password_data->DeepCopy()); | |
133 cryptohome::KeyDefinition key(password, | |
134 kCryptohomeSupervisedUserKeyLabel, | |
135 kCryptohomeSupervisedUserKeyPrivileges); | |
136 | |
137 authenticator_ = new ExtendedAuthenticator(this); | |
138 SupervisedUserAuthentication::Schema current_schema = | |
139 auth->GetPasswordSchema(user_id()); | |
140 | |
141 key.revision = revision; | |
142 | |
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 = kCryptohomeSupervisedUserIncompleteKeyPrivileges; | |
147 | |
148 VLOG(1) << "Adding new schema key"; | |
149 DCHECK(context_.GetKey()->GetLabel().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"; | |
159 | |
160 if (auth->HasIncompleteKey(user_id())) { | |
161 // We need to use Migrate instead of Authorized Update privilege. | |
162 key.privileges = kCryptohomeSupervisedUserIncompleteKeyPrivileges; | |
163 } | |
164 // Just update the key. | |
165 DCHECK_EQ(context_.GetKey()->GetLabel(), kCryptohomeSupervisedUserKeyLabel); | |
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"; | |
175 } | |
176 } | |
177 | |
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 kLegacyCryptohomeSupervisedUserKeyLabel, | |
188 base::Bind(&SupervisedUserLoginFlow::OnOldKeyRemoved, | |
189 weak_factory_.GetWeakPtr())); | |
190 } | |
191 | |
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(); | |
198 } | |
199 | |
200 void SupervisedUserLoginFlow::OnPasswordChangeDataLoadFailed() { | |
201 LOG(ERROR) << "Could not load data for password change"; | |
202 | |
203 UMA_HISTOGRAM_ENUMERATION( | |
204 "ManagedUsers.ChromeOS.PasswordChange", | |
205 SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_LOADING_DATA, | |
206 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE); | |
207 Finish(); | |
208 } | |
209 | |
210 void SupervisedUserLoginFlow::OnAuthenticationFailure( | |
211 ExtendedAuthenticator::AuthState state) { | |
212 LOG(ERROR) << "Authentication error during password change"; | |
213 | |
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(); | |
220 } | |
221 | |
222 void SupervisedUserLoginFlow::OnPasswordUpdated( | |
223 scoped_ptr<base::DictionaryValue> password_data) { | |
224 VLOG(1) << "Updated password for supervised user"; | |
225 | |
226 SupervisedUserAuthentication* auth = | |
227 UserManager::Get()->GetSupervisedUserManager()->GetAuthentication(); | |
228 | |
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 */); | |
234 | |
235 UMA_HISTOGRAM_ENUMERATION( | |
236 "ManagedUsers.ChromeOS.PasswordChange", | |
237 SupervisedUserAuthentication::PASSWORD_CHANGED_IN_USER_SESSION, | |
238 SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE); | |
239 Finish(); | |
240 } | |
241 | |
242 void SupervisedUserLoginFlow::Finish() { | |
243 LoginUtils::Get()->DoBrowserLaunch(profile_, host()); | |
244 profile_ = NULL; | |
245 UnregisterFlowSoon(); | |
246 } | |
247 | |
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())); | |
256 } | |
257 | |
258 } // namespace chromeos | |
OLD | NEW |