Roll src/third_party/WebKit abe9e39c:3d349bd (svn 182659:182669)
[chromium-blink-merge.git] / chromeos / login / auth / extended_authenticator.cc
blob0b814395cb1dc4d8d6c95e907aee1c158ac54f9b
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.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"
22 #include "third_party/cros_system_api/dbus/service_constants.h"
24 namespace chromeos {
26 namespace {
28 void RecordStartMarker(const std::string& marker) {
29 std::string full_marker = "Cryptohome-";
30 full_marker.append(marker);
31 full_marker.append("-Start");
32 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(full_marker, false);
35 void RecordEndMarker(const std::string& marker) {
36 std::string full_marker = "Cryptohome-";
37 full_marker.append(marker);
38 full_marker.append("-End");
39 chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(full_marker, false);
42 } // namespace
44 ExtendedAuthenticator::ExtendedAuthenticator(NewAuthStatusConsumer* consumer)
45 : salt_obtained_(false), consumer_(consumer), old_consumer_(NULL) {
46 SystemSaltGetter::Get()->GetSystemSalt(
47 base::Bind(&ExtendedAuthenticator::OnSaltObtained, this));
50 ExtendedAuthenticator::ExtendedAuthenticator(AuthStatusConsumer* consumer)
51 : salt_obtained_(false), consumer_(NULL), old_consumer_(consumer) {
52 SystemSaltGetter::Get()->GetSystemSalt(
53 base::Bind(&ExtendedAuthenticator::OnSaltObtained, this));
56 void ExtendedAuthenticator::SetConsumer(AuthStatusConsumer* consumer) {
57 old_consumer_ = consumer;
60 void ExtendedAuthenticator::AuthenticateToMount(
61 const UserContext& context,
62 const ResultCallback& success_callback) {
63 TransformKeyIfNeeded(context,
64 base::Bind(&ExtendedAuthenticator::DoAuthenticateToMount,
65 this,
66 success_callback));
69 void ExtendedAuthenticator::AuthenticateToCheck(
70 const UserContext& context,
71 const base::Closure& success_callback) {
72 TransformKeyIfNeeded(context,
73 base::Bind(&ExtendedAuthenticator::DoAuthenticateToCheck,
74 this,
75 success_callback));
78 void ExtendedAuthenticator::CreateMount(
79 const std::string& user_id,
80 const std::vector<cryptohome::KeyDefinition>& keys,
81 const ResultCallback& success_callback) {
82 RecordStartMarker("MountEx");
84 std::string canonicalized = gaia::CanonicalizeEmail(user_id);
85 cryptohome::Identification id(canonicalized);
86 cryptohome::Authorization auth(keys.front());
87 cryptohome::MountParameters mount(false);
88 for (size_t i = 0; i < keys.size(); i++) {
89 mount.create_keys.push_back(keys[i]);
91 UserContext context(user_id);
92 Key key(keys.front().secret);
93 key.SetLabel(keys.front().label);
94 context.SetKey(key);
96 cryptohome::HomedirMethods::GetInstance()->MountEx(
97 id,
98 auth,
99 mount,
100 base::Bind(&ExtendedAuthenticator::OnMountComplete,
101 this,
102 "MountEx",
103 context,
104 success_callback));
107 void ExtendedAuthenticator::AddKey(const UserContext& context,
108 const cryptohome::KeyDefinition& key,
109 bool replace_existing,
110 const base::Closure& success_callback) {
111 TransformKeyIfNeeded(context,
112 base::Bind(&ExtendedAuthenticator::DoAddKey,
113 this,
114 key,
115 replace_existing,
116 success_callback));
119 void ExtendedAuthenticator::UpdateKeyAuthorized(
120 const UserContext& context,
121 const cryptohome::KeyDefinition& key,
122 const std::string& signature,
123 const base::Closure& success_callback) {
124 TransformKeyIfNeeded(context,
125 base::Bind(&ExtendedAuthenticator::DoUpdateKeyAuthorized,
126 this,
127 key,
128 signature,
129 success_callback));
132 void ExtendedAuthenticator::RemoveKey(const UserContext& context,
133 const std::string& key_to_remove,
134 const base::Closure& success_callback) {
135 TransformKeyIfNeeded(context,
136 base::Bind(&ExtendedAuthenticator::DoRemoveKey,
137 this,
138 key_to_remove,
139 success_callback));
142 void ExtendedAuthenticator::TransformKeyIfNeeded(
143 const UserContext& user_context,
144 const ContextCallback& callback) {
145 if (user_context.GetKey()->GetKeyType() != Key::KEY_TYPE_PASSWORD_PLAIN) {
146 callback.Run(user_context);
147 return;
150 if (!salt_obtained_) {
151 system_salt_callbacks_.push_back(
152 base::Bind(&ExtendedAuthenticator::TransformKeyIfNeeded,
153 this,
154 user_context,
155 callback));
156 return;
159 UserContext transformed_context = user_context;
160 transformed_context.GetKey()->Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF,
161 system_salt_);
162 callback.Run(transformed_context);
165 ExtendedAuthenticator::~ExtendedAuthenticator() {
168 void ExtendedAuthenticator::OnSaltObtained(const std::string& system_salt) {
169 salt_obtained_ = true;
170 system_salt_ = system_salt;
171 for (std::vector<base::Closure>::const_iterator it =
172 system_salt_callbacks_.begin();
173 it != system_salt_callbacks_.end();
174 ++it) {
175 it->Run();
177 system_salt_callbacks_.clear();
180 void ExtendedAuthenticator::DoAuthenticateToMount(
181 const ResultCallback& success_callback,
182 const UserContext& user_context) {
183 RecordStartMarker("MountEx");
185 std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
186 cryptohome::Identification id(canonicalized);
187 const Key* const key = user_context.GetKey();
188 cryptohome::Authorization auth(key->GetSecret(), key->GetLabel());
189 cryptohome::MountParameters mount(false);
191 cryptohome::HomedirMethods::GetInstance()->MountEx(
193 auth,
194 mount,
195 base::Bind(&ExtendedAuthenticator::OnMountComplete,
196 this,
197 "MountEx",
198 user_context,
199 success_callback));
202 void ExtendedAuthenticator::DoAuthenticateToCheck(
203 const base::Closure& success_callback,
204 const UserContext& user_context) {
205 RecordStartMarker("CheckKeyEx");
207 std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
208 cryptohome::Identification id(canonicalized);
209 const Key* const key = user_context.GetKey();
210 cryptohome::Authorization auth(key->GetSecret(), key->GetLabel());
212 cryptohome::HomedirMethods::GetInstance()->CheckKeyEx(
214 auth,
215 base::Bind(&ExtendedAuthenticator::OnOperationComplete,
216 this,
217 "CheckKeyEx",
218 user_context,
219 success_callback));
222 void ExtendedAuthenticator::DoAddKey(const cryptohome::KeyDefinition& key,
223 bool replace_existing,
224 const base::Closure& success_callback,
225 const UserContext& user_context) {
226 RecordStartMarker("AddKeyEx");
228 std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
229 cryptohome::Identification id(canonicalized);
230 const Key* const auth_key = user_context.GetKey();
231 cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel());
233 cryptohome::HomedirMethods::GetInstance()->AddKeyEx(
235 auth,
236 key,
237 replace_existing,
238 base::Bind(&ExtendedAuthenticator::OnOperationComplete,
239 this,
240 "AddKeyEx",
241 user_context,
242 success_callback));
245 void ExtendedAuthenticator::DoUpdateKeyAuthorized(
246 const cryptohome::KeyDefinition& key,
247 const std::string& signature,
248 const base::Closure& success_callback,
249 const UserContext& user_context) {
250 RecordStartMarker("UpdateKeyAuthorized");
252 std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
253 cryptohome::Identification id(canonicalized);
254 const Key* const auth_key = user_context.GetKey();
255 cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel());
257 cryptohome::HomedirMethods::GetInstance()->UpdateKeyEx(
259 auth,
260 key,
261 signature,
262 base::Bind(&ExtendedAuthenticator::OnOperationComplete,
263 this,
264 "UpdateKeyAuthorized",
265 user_context,
266 success_callback));
269 void ExtendedAuthenticator::DoRemoveKey(const std::string& key_to_remove,
270 const base::Closure& success_callback,
271 const UserContext& user_context) {
272 RecordStartMarker("RemoveKeyEx");
274 std::string canonicalized = gaia::CanonicalizeEmail(user_context.GetUserID());
275 cryptohome::Identification id(canonicalized);
276 const Key* const auth_key = user_context.GetKey();
277 cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel());
279 cryptohome::HomedirMethods::GetInstance()->RemoveKeyEx(
281 auth,
282 key_to_remove,
283 base::Bind(&ExtendedAuthenticator::OnOperationComplete,
284 this,
285 "RemoveKeyEx",
286 user_context,
287 success_callback));
290 void ExtendedAuthenticator::OnMountComplete(
291 const std::string& time_marker,
292 const UserContext& user_context,
293 const ResultCallback& success_callback,
294 bool success,
295 cryptohome::MountError return_code,
296 const std::string& mount_hash) {
297 RecordEndMarker(time_marker);
298 UserContext copy = user_context;
299 copy.SetUserIDHash(mount_hash);
300 if (return_code == cryptohome::MOUNT_ERROR_NONE) {
301 if (!success_callback.is_null())
302 success_callback.Run(mount_hash);
303 if (old_consumer_)
304 old_consumer_->OnAuthSuccess(copy);
305 return;
307 AuthState state = FAILED_MOUNT;
308 if (return_code == cryptohome::MOUNT_ERROR_TPM_COMM_ERROR ||
309 return_code == cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK ||
310 return_code == cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) {
311 state = FAILED_TPM;
313 if (return_code == cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST) {
314 state = NO_MOUNT;
316 if (consumer_)
317 consumer_->OnAuthenticationFailure(state);
318 if (old_consumer_) {
319 AuthFailure failure(AuthFailure::COULD_NOT_MOUNT_CRYPTOHOME);
320 old_consumer_->OnAuthFailure(failure);
324 void ExtendedAuthenticator::OnOperationComplete(
325 const std::string& time_marker,
326 const UserContext& user_context,
327 const base::Closure& success_callback,
328 bool success,
329 cryptohome::MountError return_code) {
330 RecordEndMarker(time_marker);
331 if (return_code == cryptohome::MOUNT_ERROR_NONE) {
332 if (!success_callback.is_null())
333 success_callback.Run();
334 if (old_consumer_)
335 old_consumer_->OnAuthSuccess(user_context);
336 return;
339 LOG(ERROR) << "Supervised user cryptohome error, code: " << return_code;
341 AuthState state = FAILED_MOUNT;
343 if (return_code == cryptohome::MOUNT_ERROR_TPM_COMM_ERROR ||
344 return_code == cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK ||
345 return_code == cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) {
346 state = FAILED_TPM;
349 if (return_code == cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST)
350 state = NO_MOUNT;
352 if (consumer_)
353 consumer_->OnAuthenticationFailure(state);
355 if (old_consumer_) {
356 AuthFailure failure(AuthFailure::UNLOCK_FAILED);
357 old_consumer_->OnAuthFailure(failure);
361 } // namespace chromeos