15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/supervised_user/chromeos/manager_password_service.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h"
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/logging.h"
923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/metrics/histogram.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/values.h"
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/login/supervised/supervised_user_authentication.h"
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/login/supervised/supervised_user_constants.h"
136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/supervised_user/supervised_user_constants.h"
16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "chrome/browser/supervised_user/supervised_user_sync_service.h"
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chromeos/login/auth/key.h"
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chromeos/login/auth/user_context.h"
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/user_manager/user.h"
206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/user_manager/user_manager.h"
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/user_manager/user_type.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)namespace chromeos {
2423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ManagerPasswordService::ManagerPasswordService() : weak_ptr_factory_(this) {}
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ManagerPasswordService::~ManagerPasswordService() {}
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ManagerPasswordService::Init(
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& user_id,
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SupervisedUserSyncService* user_service,
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SupervisedUserSharedSettingsService* shared_settings_service) {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  user_id_ = user_id;
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  user_service_ = user_service;
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  settings_service_ = shared_settings_service;
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  settings_service_subscription_ = settings_service_->Subscribe(
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&ManagerPasswordService::OnSharedSettingsChange,
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4029b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch  authenticator_ = ExtendedAuthenticator::Create(this);
4123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  SupervisedUserManager* supervised_user_manager =
436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      ChromeUserManager::Get()->GetSupervisedUserManager();
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const user_manager::UserList& users =
466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      user_manager::UserManager::Get()->GetUsers();
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (user_manager::UserList::const_iterator it = users.begin();
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       it != users.end();
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       ++it) {
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if ((*it)->GetType() != user_manager::USER_TYPE_SUPERVISED)
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (user_id != supervised_user_manager->GetManagerUserId((*it)->email()))
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    OnSharedSettingsChange(
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        supervised_user_manager->GetUserSyncId((*it)->email()),
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        supervised_users::kChromeOSPasswordData);
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ManagerPasswordService::OnSharedSettingsChange(
62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::string& su_id,
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& key) {
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (key != supervised_users::kChromeOSPasswordData)
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  SupervisedUserManager* supervised_user_manager =
686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      ChromeUserManager::Get()->GetSupervisedUserManager();
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const user_manager::User* user = supervised_user_manager->FindBySyncId(su_id);
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // No user on device.
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (user == NULL)
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const base::Value* value = settings_service_->GetValue(su_id, key);
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (value == NULL) {
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(WARNING) << "Got empty value from sync.";
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* dict;
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!value->GetAsDictionary(&dict)) {
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(WARNING) << "Got non-dictionary value from sync.";
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  SupervisedUserAuthentication* auth =
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      supervised_user_manager->GetAuthentication();
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!auth->NeedPasswordChange(user->email(), dict) &&
90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      !auth->HasIncompleteKey(user->email())) {
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  scoped_ptr<base::DictionaryValue> wrapper(dict->DeepCopy());
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  user_service_->GetSupervisedUsersAsync(
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      base::Bind(&ManagerPasswordService::GetSupervisedUsersCallback,
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                 su_id,
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 user->email(),
99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 Passed(&wrapper)));
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ManagerPasswordService::GetSupervisedUsersCallback(
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::string& sync_su_id,
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& user_id,
105effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    scoped_ptr<base::DictionaryValue> password_data,
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const base::DictionaryValue* supervised_users) {
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const base::DictionaryValue* supervised_user = NULL;
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!supervised_users->GetDictionary(sync_su_id, &supervised_user))
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string master_key;
11123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  std::string encryption_key;
11223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  std::string signature_key;
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!supervised_user->GetString(SupervisedUserSyncService::kMasterKey,
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                  &master_key)) {
11523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    LOG(WARNING) << "Can not apply password change to " << user_id
11623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                 << ": no master key found";
11723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION(
11823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        "ManagedUsers.ChromeOS.PasswordChange",
11923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_NO_MASTER_KEY,
12023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
12123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
12223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
12323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!supervised_user->GetString(
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          SupervisedUserSyncService::kPasswordSignatureKey, &signature_key) ||
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      !supervised_user->GetString(
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          SupervisedUserSyncService::kPasswordEncryptionKey,
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          &encryption_key)) {
12923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    LOG(WARNING) << "Can not apply password change to " << user_id
13023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                 << ": no signature / encryption keys.";
13123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION(
13223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        "ManagedUsers.ChromeOS.PasswordChange",
13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_NO_SIGNATURE_KEY,
13423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
13523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
13623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
13723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UserContext manager_key(user_id);
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  manager_key.SetKey(Key(master_key));
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  manager_key.SetIsUsingOAuth(false);
14123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
14223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // As master key can have old label, leave label field empty - it will work
14323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // as wildcard.
14423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
14523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  std::string new_key;
14623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int revision;
14723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
14823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  bool has_data = password_data->GetStringWithoutPathExpansion(
14923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      kEncryptedPassword, &new_key);
15023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  has_data &= password_data->GetIntegerWithoutPathExpansion(kPasswordRevision,
15123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                                            &revision);
15223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!has_data) {
15323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    LOG(WARNING) << "Can not apply password change to " << user_id
15423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                 << ": incomplete password data.";
15523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION(
15623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        "ManagedUsers.ChromeOS.PasswordChange",
15723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_NO_PASSWORD_DATA,
15823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
16023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
16123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
16223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  cryptohome::KeyDefinition new_key_definition(
16323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      new_key,
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      kCryptohomeSupervisedUserKeyLabel,
16523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      cryptohome::PRIV_AUTHORIZED_UPDATE || cryptohome::PRIV_MOUNT);
16623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  new_key_definition.revision = revision;
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_key_definition.authorization_data.push_back(
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      cryptohome::KeyDefinition::AuthorizationData(true /* encrypt */,
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                   false /* sign */,
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                   encryption_key));
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  new_key_definition.authorization_data.push_back(
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      cryptohome::KeyDefinition::AuthorizationData(false /* encrypt */,
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                   true /* sign */,
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                   signature_key));
17523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
17623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  authenticator_->AddKey(manager_key,
17723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                         new_key_definition,
17823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                         true /* replace existing */,
17923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                         base::Bind(&ManagerPasswordService::OnAddKeySuccess,
18023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                    weak_ptr_factory_.GetWeakPtr(),
181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                    manager_key,
18223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                    user_id,
183effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                    Passed(&password_data)));
18423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
18523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
18623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void ManagerPasswordService::OnAuthenticationFailure(
18723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    ExtendedAuthenticator::AuthState state) {
18823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(
18923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      "ManagedUsers.ChromeOS.PasswordChange",
19023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_MASTER_KEY_FAILURE,
19123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
19223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  LOG(ERROR) << "Can not apply password change, master key failure";
19323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
19423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
19523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void ManagerPasswordService::OnAddKeySuccess(
196effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const UserContext& master_key_context,
19723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const std::string& user_id,
198effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    scoped_ptr<base::DictionaryValue> password_data) {
19923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  VLOG(0) << "Password changed for " << user_id;
20023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(
20123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      "ManagedUsers.ChromeOS.PasswordChange",
20223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      SupervisedUserAuthentication::PASSWORD_CHANGED_IN_MANAGER_SESSION,
20323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
20423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
20523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  SupervisedUserAuthentication* auth =
2066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      ChromeUserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  int old_schema = auth->GetPasswordSchema(user_id);
208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  auth->StorePasswordData(user_id, *password_data.get());
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (auth->HasIncompleteKey(user_id))
211c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    auth->MarkKeyIncomplete(user_id, false /* key is complete now */);
212c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
213c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Check if we have legacy labels for keys.
214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // TODO(antrim): Migrate it to GetLabels call once wad@ implement it.
215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (old_schema == SupervisedUserAuthentication::SCHEMA_PLAIN) {
216effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // 1) Add new manager key (using old key).
217effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // 2) Remove old supervised user key.
218effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // 3) Remove old manager key.
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    authenticator_->TransformKeyIfNeeded(
220effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        master_key_context,
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(&ManagerPasswordService::OnKeyTransformedIfNeeded,
222effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   weak_ptr_factory_.GetWeakPtr()));
223effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
224effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
225effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ManagerPasswordService::OnKeyTransformedIfNeeded(
227effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const UserContext& master_key_context) {
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const Key* const key = master_key_context.GetKey();
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_NE(Key::KEY_TYPE_PASSWORD_PLAIN, key->GetKeyType());
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  cryptohome::KeyDefinition new_master_key(key->GetSecret(),
231effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                           kCryptohomeMasterKeyLabel,
232effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                           cryptohome::PRIV_DEFAULT);
233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Use new master key for further actions.
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UserContext new_master_key_context = master_key_context;
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  new_master_key_context.GetKey()->SetLabel(kCryptohomeMasterKeyLabel);
236effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  authenticator_->AddKey(
237effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      master_key_context,
238effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      new_master_key,
239effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      true /* replace existing */,
240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::Bind(&ManagerPasswordService::OnNewManagerKeySuccess,
241effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 weak_ptr_factory_.GetWeakPtr(),
242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                 new_master_key_context));
243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
244effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
245effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ManagerPasswordService::OnNewManagerKeySuccess(
246effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const UserContext& master_key_context) {
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  VLOG(1) << "Added new master key for " << master_key_context.GetUserID();
248effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  authenticator_->RemoveKey(
249effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      master_key_context,
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      kLegacyCryptohomeSupervisedUserKeyLabel,
251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      base::Bind(&ManagerPasswordService::OnOldSupervisedUserKeyDeleted,
252effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 weak_ptr_factory_.GetWeakPtr(),
253effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 master_key_context));
254effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
255effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void ManagerPasswordService::OnOldSupervisedUserKeyDeleted(
257effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const UserContext& master_key_context) {
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  VLOG(1) << "Removed old supervised user key for "
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          << master_key_context.GetUserID();
260effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  authenticator_->RemoveKey(
261effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      master_key_context,
262effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      kLegacyCryptohomeMasterKeyLabel,
263effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      base::Bind(&ManagerPasswordService::OnOldManagerKeyDeleted,
264effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 weak_ptr_factory_.GetWeakPtr(),
265effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                 master_key_context));
266effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
267effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
268effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ManagerPasswordService::OnOldManagerKeyDeleted(
269effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const UserContext& master_key_context) {
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  VLOG(1) << "Removed old master key for " << master_key_context.GetUserID();
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ManagerPasswordService::Shutdown() {
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  settings_service_subscription_.reset();
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
27623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
27723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}  // namespace chromeos
278