Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chromeos / login / auth / extended_authenticator_impl.cc
blob0aa10e59b76fac6235366d3ec576feba59c0677f
1 // Copyright 2014 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 "chromeos/login/auth/extended_authenticator_impl.h"
7 #include "base/bind.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_util.h"
10 #include "chromeos/cryptohome/async_method_caller.h"
11 #include "chromeos/cryptohome/cryptohome_parameters.h"
12 #include "chromeos/cryptohome/homedir_methods.h"
13 #include "chromeos/cryptohome/system_salt_getter.h"
14 #include "chromeos/dbus/cryptohome_client.h"
15 #include "chromeos/dbus/dbus_thread_manager.h"
16 #include "chromeos/login/auth/auth_status_consumer.h"
17 #include "chromeos/login/auth/key.h"
18 #include "chromeos/login/auth/user_context.h"
19 #include "chromeos/login_event_recorder.h"
20 #include "crypto/sha2.h"
21 #include "google_apis/gaia/gaia_auth_util.h"
23 namespace chromeos {
25 namespace {
27 void RecordStartMarker(const std::string& marker) {
28 std::string full_marker = "Cryptohome-";
29 full_marker.append(marker);
30 full_marker.append("-Start");
31 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(full_marker, false);
34 void RecordEndMarker(const std::string& marker) {
35 std::string full_marker = "Cryptohome-";
36 full_marker.append(marker);
37 full_marker.append("-End");
38 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(full_marker, false);
41 } // namespace
43 ExtendedAuthenticatorImpl::ExtendedAuthenticatorImpl(
44 NewAuthStatusConsumer* consumer)
45 : salt_obtained_(false), consumer_(consumer), old_consumer_(NULL) {
46 SystemSaltGetter::Get()->GetSystemSalt(
47 base::Bind(&ExtendedAuthenticatorImpl::OnSaltObtained, this));
50 ExtendedAuthenticatorImpl::ExtendedAuthenticatorImpl(
51 AuthStatusConsumer* consumer)
52 : salt_obtained_(false), consumer_(NULL), old_consumer_(consumer) {
53 SystemSaltGetter::Get()->GetSystemSalt(
54 base::Bind(&ExtendedAuthenticatorImpl::OnSaltObtained, this));
57 void ExtendedAuthenticatorImpl::SetConsumer(AuthStatusConsumer* consumer) {
58 old_consumer_ = consumer;
61 void ExtendedAuthenticatorImpl::AuthenticateToMount(
62 const UserContext& context,
63 const ResultCallback& success_callback) {
64 TransformKeyIfNeeded(
65 context,
66 base::Bind(&ExtendedAuthenticatorImpl::DoAuthenticateToMount,
67 this,
68 success_callback));
71 void ExtendedAuthenticatorImpl::AuthenticateToCheck(
72 const UserContext& context,
73 const base::Closure& success_callback) {
74 TransformKeyIfNeeded(
75 context,
76 base::Bind(&ExtendedAuthenticatorImpl::DoAuthenticateToCheck,
77 this,
78 success_callback));
81 void ExtendedAuthenticatorImpl::CreateMount(
82 const std::string& user_id,
83 const std::vector<cryptohome::KeyDefinition>& keys,
84 const ResultCallback& success_callback) {
85 RecordStartMarker("MountEx");
87 std::string canonicalized = gaia::CanonicalizeEmail(user_id);
88 cryptohome::Identification id(canonicalized);
89 cryptohome::Authorization auth(keys.front());
90 cryptohome::MountParameters mount(false);
91 for (size_t i = 0; i < keys.size(); i++) {
92 mount.create_keys.push_back(keys[i]);
94 UserContext context(user_id);
95 Key key(keys.front().secret);
96 key.SetLabel(keys.front().label);
97 context.SetKey(key);
99 cryptohome::HomedirMethods::GetInstance()->MountEx(
101 auth,
102 mount,
103 base::Bind(&ExtendedAuthenticatorImpl::OnMountComplete,
104 this,
105 "MountEx",
106 context,
107 success_callback));
110 void ExtendedAuthenticatorImpl::AddKey(const UserContext& context,
111 const cryptohome::KeyDefinition& key,
112 bool replace_existing,
113 const base::Closure& success_callback) {
114 TransformKeyIfNeeded(context,
115 base::Bind(&ExtendedAuthenticatorImpl::DoAddKey,
116 this,
117 key,
118 replace_existing,
119 success_callback));
122 void ExtendedAuthenticatorImpl::UpdateKeyAuthorized(
123 const UserContext& context,
124 const cryptohome::KeyDefinition& key,
125 const std::string& signature,
126 const base::Closure& success_callback) {
127 TransformKeyIfNeeded(
128 context,
129 base::Bind(&ExtendedAuthenticatorImpl::DoUpdateKeyAuthorized,
130 this,
131 key,
132 signature,
133 success_callback));
136 void ExtendedAuthenticatorImpl::RemoveKey(const UserContext& context,
137 const std::string& key_to_remove,
138 const base::Closure& success_callback) {
139 TransformKeyIfNeeded(context,
140 base::Bind(&ExtendedAuthenticatorImpl::DoRemoveKey,
141 this,
142 key_to_remove,
143 success_callback));
146 void ExtendedAuthenticatorImpl::TransformKeyIfNeeded(
147 const UserContext& user_context,
148 const ContextCallback& callback) {
149 if (user_context.GetKey()->GetKeyType() != Key::KEY_TYPE_PASSWORD_PLAIN) {
150 callback.Run(user_context);
151 return;
154 if (!salt_obtained_) {
155 system_salt_callbacks_.push_back(
156 base::Bind(&ExtendedAuthenticatorImpl::TransformKeyIfNeeded,
157 this,
158 user_context,
159 callback));
160 return;
163 UserContext transformed_context = user_context;
164 transformed_context.GetKey()->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF,
165 system_salt_);
166 callback.Run(transformed_context);
169 ExtendedAuthenticatorImpl::~ExtendedAuthenticatorImpl() {
172 void ExtendedAuthenticatorImpl::OnSaltObtained(const std::string& system_salt) {
173 salt_obtained_ = true;
174 system_salt_ = system_salt;
175 for (std::vector<base::Closure>::const_iterator it =
176 system_salt_callbacks_.begin();
177 it != system_salt_callbacks_.end();
178 ++it) {
179 it->Run();
181 system_salt_callbacks_.clear();
184 void ExtendedAuthenticatorImpl::DoAuthenticateToMount(
185 const ResultCallback& success_callback,
186 const UserContext& user_context) {
187 RecordStartMarker("MountEx");
189 std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
190 cryptohome::Identification id(canonicalized);
191 const Key* const key = user_context.GetKey();
192 cryptohome::Authorization auth(key->GetSecret(), key->GetLabel());
193 cryptohome::MountParameters mount(false);
195 cryptohome::HomedirMethods::GetInstance()->MountEx(
197 auth,
198 mount,
199 base::Bind(&ExtendedAuthenticatorImpl::OnMountComplete,
200 this,
201 "MountEx",
202 user_context,
203 success_callback));
206 void ExtendedAuthenticatorImpl::DoAuthenticateToCheck(
207 const base::Closure& success_callback,
208 const UserContext& user_context) {
209 RecordStartMarker("CheckKeyEx");
211 std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
212 cryptohome::Identification id(canonicalized);
213 const Key* const key = user_context.GetKey();
214 cryptohome::Authorization auth(key->GetSecret(), key->GetLabel());
216 cryptohome::HomedirMethods::GetInstance()->CheckKeyEx(
218 auth,
219 base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete,
220 this,
221 "CheckKeyEx",
222 user_context,
223 success_callback));
226 void ExtendedAuthenticatorImpl::DoAddKey(const cryptohome::KeyDefinition& key,
227 bool replace_existing,
228 const base::Closure& success_callback,
229 const UserContext& user_context) {
230 RecordStartMarker("AddKeyEx");
232 std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
233 cryptohome::Identification id(canonicalized);
234 const Key* const auth_key = user_context.GetKey();
235 cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel());
237 cryptohome::HomedirMethods::GetInstance()->AddKeyEx(
239 auth,
240 key,
241 replace_existing,
242 base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete,
243 this,
244 "AddKeyEx",
245 user_context,
246 success_callback));
249 void ExtendedAuthenticatorImpl::DoUpdateKeyAuthorized(
250 const cryptohome::KeyDefinition& key,
251 const std::string& signature,
252 const base::Closure& success_callback,
253 const UserContext& user_context) {
254 RecordStartMarker("UpdateKeyAuthorized");
256 std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
257 cryptohome::Identification id(canonicalized);
258 const Key* const auth_key = user_context.GetKey();
259 cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel());
261 cryptohome::HomedirMethods::GetInstance()->UpdateKeyEx(
263 auth,
264 key,
265 signature,
266 base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete,
267 this,
268 "UpdateKeyAuthorized",
269 user_context,
270 success_callback));
273 void ExtendedAuthenticatorImpl::DoRemoveKey(const std::string& key_to_remove,
274 const base::Closure& success_callback,
275 const UserContext& user_context) {
276 RecordStartMarker("RemoveKeyEx");
278 std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
279 cryptohome::Identification id(canonicalized);
280 const Key* const auth_key = user_context.GetKey();
281 cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel());
283 cryptohome::HomedirMethods::GetInstance()->RemoveKeyEx(
285 auth,
286 key_to_remove,
287 base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete,
288 this,
289 "RemoveKeyEx",
290 user_context,
291 success_callback));
294 void ExtendedAuthenticatorImpl::OnMountComplete(
295 const std::string& time_marker,
296 const UserContext& user_context,
297 const ResultCallback& success_callback,
298 bool success,
299 cryptohome::MountError return_code,
300 const std::string& mount_hash) {
301 RecordEndMarker(time_marker);
302 UserContext copy = user_context;
303 copy.SetUserIDHash(mount_hash);
304 if (return_code == cryptohome::MOUNT_ERROR_NONE) {
305 if (!success_callback.is_null())
306 success_callback.Run(mount_hash);
307 if (old_consumer_)
308 old_consumer_->OnAuthSuccess(copy);
309 return;
311 AuthState state = FAILED_MOUNT;
312 if (return_code == cryptohome::MOUNT_ERROR_TPM_COMM_ERROR ||
313 return_code == cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK ||
314 return_code == cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) {
315 state = FAILED_TPM;
317 if (return_code == cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST) {
318 state = NO_MOUNT;
320 if (consumer_)
321 consumer_->OnAuthenticationFailure(state);
322 if (old_consumer_) {
323 AuthFailure failure(AuthFailure::COULD_NOT_MOUNT_CRYPTOHOME);
324 old_consumer_->OnAuthFailure(failure);
328 void ExtendedAuthenticatorImpl::OnOperationComplete(
329 const std::string& time_marker,
330 const UserContext& user_context,
331 const base::Closure& success_callback,
332 bool success,
333 cryptohome::MountError return_code) {
334 RecordEndMarker(time_marker);
335 if (return_code == cryptohome::MOUNT_ERROR_NONE) {
336 if (!success_callback.is_null())
337 success_callback.Run();
338 if (old_consumer_)
339 old_consumer_->OnAuthSuccess(user_context);
340 return;
343 LOG(ERROR) << "Supervised user cryptohome error, code: " << return_code;
345 AuthState state = FAILED_MOUNT;
347 if (return_code == cryptohome::MOUNT_ERROR_TPM_COMM_ERROR ||
348 return_code == cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK ||
349 return_code == cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) {
350 state = FAILED_TPM;
353 if (return_code == cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST)
354 state = NO_MOUNT;
356 if (consumer_)
357 consumer_->OnAuthenticationFailure(state);
359 if (old_consumer_) {
360 AuthFailure failure(AuthFailure::UNLOCK_FAILED);
361 old_consumer_->OnAuthFailure(failure);
365 } // namespace chromeos