// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Unit tests for UserSession.

#include "cryptohome/user_session.h"

#include <string>
#include <vector>

#include <base/memory/ref_counted.h>
#include <base/test/task_environment.h>
#include <brillo/cryptohome.h>
#include <brillo/secure_blob.h>
#include <gtest/gtest.h>
#include <policy/libpolicy.h>
#include <policy/mock_device_policy.h>

#include "cryptohome/credentials.h"
#include "cryptohome/crypto.h"
#include "cryptohome/crypto/hmac.h"
#include "cryptohome/crypto/secure_blob_util.h"
#include "cryptohome/filesystem_layout.h"
#include "cryptohome/keyset_management.h"
#include "cryptohome/mock_keyset_management.h"
#include "cryptohome/mock_platform.h"
#include "cryptohome/pkcs11/fake_pkcs11_token.h"
#include "cryptohome/pkcs11/mock_pkcs11_token_factory.h"
#include "cryptohome/storage/homedirs.h"
#include "cryptohome/storage/mock_mount.h"

using brillo::SecureBlob;

using ::testing::_;
using ::testing::ByRef;
using ::testing::DoAll;
using ::testing::Eq;
using ::testing::Invoke;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::SetArgPointee;

namespace cryptohome {

namespace {

constexpr char kUser0[] = "First User";
constexpr char kUserPassword0[] = "user0_pass";
constexpr char kWebAuthnSecretHmacMessage[] = "AuthTimeWebAuthnSecret";

}  // namespace

class UserSessionTest : public ::testing::Test {
 public:
  UserSessionTest() : crypto_(&platform_) {}
  ~UserSessionTest() override {}

  // Not copyable or movable
  UserSessionTest(const UserSessionTest&) = delete;
  UserSessionTest& operator=(const UserSessionTest&) = delete;
  UserSessionTest(UserSessionTest&&) = delete;
  UserSessionTest& operator=(UserSessionTest&&) = delete;

  void SetUp() override {
    InitializeFilesystemLayout(&platform_, &crypto_, &system_salt_);
    keyset_management_ = std::make_unique<KeysetManagement>(
        &platform_, &crypto_, system_salt_,
        std::make_unique<VaultKeysetFactory>());
    user_activity_timestamp_manager_ =
        std::make_unique<UserOldestActivityTimestampManager>(&platform_);
    HomeDirs::RemoveCallback remove_callback;
    mock_device_policy_ = new policy::MockDevicePolicy();
    homedirs_ = std::make_unique<HomeDirs>(
        &platform_,
        std::make_unique<policy::PolicyProvider>(
            std::unique_ptr<policy::MockDevicePolicy>(mock_device_policy_)),
        remove_callback);

    platform_.GetFake()->SetSystemSaltForLibbrillo(system_salt_);

    AddUser(kUser0, kUserPassword0);

    PrepareDirectoryStructure();

    homedirs_->Create(kUser0);
    keyset_management_->AddInitialKeyset(users_[0].credentials);

    mount_ = new NiceMock<MockMount>();

    ON_CALL(pkcs11_token_factory_, New(_, _, _))
        .WillByDefault(Invoke([](const std::string& username,
                                 const base::FilePath& token_dir,
                                 const brillo::SecureBlob& auth_data) {
          return std::make_unique<FakePkcs11Token>();
        }));

    session_ = new UserSession(homedirs_.get(), keyset_management_.get(),
                               user_activity_timestamp_manager_.get(),
                               &pkcs11_token_factory_, system_salt_, mount_);
  }

  void TearDown() override {
    platform_.GetFake()->RemoveSystemSaltForLibbrillo();
  }

 protected:
  struct UserInfo {
    std::string name;
    std::string obfuscated;
    brillo::SecureBlob passkey;
    Credentials credentials;
    base::FilePath homedir_path;
    base::FilePath user_path;
  };

  // Information about users' homedirs. The order of users is equal to kUsers.
  std::vector<UserInfo> users_;
  NiceMock<MockPlatform> platform_;
  NiceMock<MockPkcs11TokenFactory> pkcs11_token_factory_;
  Crypto crypto_;
  brillo::SecureBlob system_salt_;
  std::unique_ptr<KeysetManagement> keyset_management_;
  policy::MockDevicePolicy* mock_device_policy_;  // owned by homedirs_
  std::unique_ptr<UserOldestActivityTimestampManager>
      user_activity_timestamp_manager_;
  std::unique_ptr<HomeDirs> homedirs_;
  scoped_refptr<UserSession> session_;
  // TODO(dlunev): Replace with real mount when FakePlatform is mature enough
  // to support it mock-less.
  scoped_refptr<MockMount> mount_;
  base::test::TaskEnvironment task_environment_{
      base::test::TaskEnvironment::TimeSource::MOCK_TIME};

  void AddUser(const char* name, const char* password) {
    std::string obfuscated =
        brillo::cryptohome::home::SanitizeUserNameWithSalt(name, system_salt_);
    brillo::SecureBlob passkey;
    cryptohome::Crypto::PasswordToPasskey(password, system_salt_, &passkey);
    Credentials credentials(name, passkey);

    UserInfo info = {name,
                     obfuscated,
                     passkey,
                     credentials,
                     ShadowRoot().Append(obfuscated),
                     brillo::cryptohome::home::GetHashedUserPath(obfuscated)};
    users_.push_back(info);
  }

  void PrepareDirectoryStructure() {
    ASSERT_TRUE(platform_.CreateDirectory(ShadowRoot()));
    ASSERT_TRUE(platform_.CreateDirectory(
        brillo::cryptohome::home::GetUserPathPrefix()));
  }

  void PreparePolicy(bool enterprise_owned, const std::string& owner) {
    homedirs_->set_enterprise_owned(enterprise_owned);
    EXPECT_CALL(*mock_device_policy_, LoadPolicy())
        .WillRepeatedly(Return(true));
    EXPECT_CALL(*mock_device_policy_, GetOwner(_))
        .WillRepeatedly(DoAll(SetArgPointee<0>(owner), Return(!owner.empty())));
  }
};

MATCHER_P(VaultOptionsEqual, options, "") {
  return memcmp(&options, &arg, sizeof(options)) == 0;
}

// Mount twice: first time with create, and the second time for the existing
// one.
TEST_F(UserSessionTest, MountVaultOk) {
  // SETUP

  const base::Time kTs1 = base::Time::FromInternalValue(42);
  const base::Time kTs2 = base::Time::FromInternalValue(43);
  const base::Time kTs3 = base::Time::FromInternalValue(44);

  // Test with ecryptfs since it has a simpler existence check.
  CryptohomeVault::Options options = {
      .force_type = EncryptedContainerType::kEcryptfs,
  };

  // Set the credentials with |users_[0].credentials| so that
  // |obfuscated_username_| is explicitly set during the Unmount test.
  session_->SetCredentials(users_[0].credentials);
  std::unique_ptr<VaultKeyset> vk = keyset_management_->GetValidKeyset(
      users_[0].credentials, nullptr /*error*/);
  FileSystemKeyset fs_keyset(*vk.get());
  EXPECT_CALL(*mount_,
              MountCryptohome(users_[0].name, _, VaultOptionsEqual(options)))
      .WillOnce(Return(MOUNT_ERROR_NONE));
  EXPECT_CALL(platform_, GetCurrentTime()).WillOnce(Return(kTs1));

  // TEST

  EXPECT_EQ(MOUNT_ERROR_NONE,
            session_->MountVault(users_[0].name, fs_keyset, options));

  // VERIFY
  // Vault created.
  EXPECT_THAT(user_activity_timestamp_manager_->GetLastUserActivityTimestamp(
                  users_[0].obfuscated),
              Eq(kTs1));
  EXPECT_NE(session_->GetWebAuthnSecret(), nullptr);
  EXPECT_FALSE(session_->GetWebAuthnSecretHash().empty());

  EXPECT_NE(session_->GetPkcs11Token(), nullptr);
  ASSERT_FALSE(session_->GetPkcs11Token()->IsReady());
  ASSERT_TRUE(session_->GetPkcs11Token()->Insert());
  ASSERT_TRUE(session_->GetPkcs11Token()->IsReady());

  // SETUP

  // TODO(dlunev): this is required to mimic a real Mount::PrepareCryptohome
  // call. Remove it when we are not mocking mount.
  platform_.CreateDirectory(GetEcryptfsUserVaultPath(users_[0].obfuscated));

  // Mount args with no create.
  options = {};

  // Set the credentials with |users_[0].credentials| so that
  // |obfuscated_username_| is explicitly set during the Unmount test.
  session_->SetCredentials(users_[0].credentials);
  EXPECT_CALL(*mount_,
              MountCryptohome(users_[0].name, _, VaultOptionsEqual(options)))
      .WillOnce(Return(MOUNT_ERROR_NONE));
  EXPECT_CALL(platform_, GetCurrentTime()).WillOnce(Return(kTs2));

  // TEST

  EXPECT_EQ(MOUNT_ERROR_NONE,
            session_->MountVault(users_[0].name, fs_keyset, options));

  // VERIFY
  // Vault still exists when tried to remount with no create.
  // ts updated on mount
  EXPECT_TRUE(platform_.DirectoryExists(users_[0].homedir_path));
  EXPECT_THAT(user_activity_timestamp_manager_->GetLastUserActivityTimestamp(
                  users_[0].obfuscated),
              Eq(kTs2));

  ASSERT_FALSE(session_->GetPkcs11Token()->IsReady());
  ASSERT_TRUE(session_->GetPkcs11Token()->Insert());
  ASSERT_TRUE(session_->GetPkcs11Token()->IsReady());

  // SETUP
  // Set the credentials with |users_[0].credentials| so that
  // |obfuscated_username_| is explicitly set during the Unmount test.
  session_->SetCredentials(users_[0].credentials);
  EXPECT_CALL(*mount_, IsNonEphemeralMounted()).WillOnce(Return(true));
  EXPECT_CALL(platform_, GetCurrentTime()).WillOnce(Return(kTs3));
  EXPECT_CALL(*mount_, UnmountCryptohome()).WillOnce(Return(true));

  // TEST

  ASSERT_TRUE(session_->Unmount());

  // VERIFY
  // ts updated on unmount
  EXPECT_THAT(user_activity_timestamp_manager_->GetLastUserActivityTimestamp(
                  users_[0].obfuscated),
              Eq(kTs3));
  EXPECT_EQ(session_->GetPkcs11Token(), nullptr);
}

TEST_F(UserSessionTest, EphemeralMountPolicyTest) {
  EXPECT_CALL(*mount_, MountEphemeralCryptohome(_))
      .WillRepeatedly(Return(MOUNT_ERROR_NONE));

  struct PolicyTestCase {
    std::string name;
    bool is_enterprise;
    std::string owner;
    std::string user;
    MountError expected_result;
  };

  std::vector<PolicyTestCase> test_cases{
      {
          .name = "NotEnterprise_NoOwner_UserLogin_OK",
          .is_enterprise = false,
          .owner = "",
          .user = "some_user",
          .expected_result = MOUNT_ERROR_EPHEMERAL_MOUNT_BY_OWNER,
      },
      {
          .name = "NotEnterprise_Owner_UserLogin_OK",
          .is_enterprise = false,
          .owner = "owner",
          .user = "some_user",
          .expected_result = MOUNT_ERROR_NONE,
      },
      {
          .name = "NotEnterprise_Owner_OwnerLogin_Error",
          .is_enterprise = false,
          .owner = "owner",
          .user = "owner",
          .expected_result = MOUNT_ERROR_EPHEMERAL_MOUNT_BY_OWNER,
      },
      {
          .name = "Enterprise_NoOwner_UserLogin_OK",
          .is_enterprise = true,
          .owner = "",
          .user = "some_user",
          .expected_result = MOUNT_ERROR_NONE,
      },
      {
          .name = "Enterprise_Owner_UserLogin_OK",
          .is_enterprise = true,
          .owner = "owner",
          .user = "some_user",
          .expected_result = MOUNT_ERROR_NONE,
      },
      {
          .name = "Enterprise_Owner_OwnerLogin_OK",
          .is_enterprise = true,
          .owner = "owner",
          .user = "owner",
          .expected_result = MOUNT_ERROR_NONE,
      },
  };

  for (const auto& test_case : test_cases) {
    PreparePolicy(test_case.is_enterprise, test_case.owner);
    ASSERT_THAT(session_->MountEphemeral(test_case.user),
                test_case.expected_result)
        << "Test case: " << test_case.name;
  }
}

// WebAuthn secret is cleared after read once.
TEST_F(UserSessionTest, WebAuthnSecretReadTwice) {
  // SETUP
  // Test with ecryptfs since it has a simpler existence check.
  CryptohomeVault::Options options = {
      .force_type = EncryptedContainerType::kEcryptfs,
  };
  MountError code = MOUNT_ERROR_NONE;
  std::unique_ptr<VaultKeyset> vk =
      keyset_management_->GetValidKeyset(users_[0].credentials, &code);
  EXPECT_EQ(code, MOUNT_ERROR_NONE);
  EXPECT_NE(vk, nullptr);

  FileSystemKeyset fs_keyset(*vk.get());
  EXPECT_CALL(*mount_,
              MountCryptohome(users_[0].name, _, VaultOptionsEqual(options)))
      .WillOnce(Return(MOUNT_ERROR_NONE));

  EXPECT_EQ(MOUNT_ERROR_NONE,
            session_->MountVault(users_[0].name, fs_keyset, options));
  const std::string message(kWebAuthnSecretHmacMessage);
  auto expected_webauthn_secret = std::make_unique<brillo::SecureBlob>(
      HmacSha256(brillo::SecureBlob::Combine(fs_keyset.Key().fnek,
                                             fs_keyset.Key().fek),
                 brillo::Blob(message.cbegin(), message.cend())));
  EXPECT_NE(expected_webauthn_secret, nullptr);

  // TEST

  std::unique_ptr<brillo::SecureBlob> actual_webauthn_secret =
      session_->GetWebAuthnSecret();
  EXPECT_NE(actual_webauthn_secret, nullptr);
  EXPECT_EQ(*actual_webauthn_secret, *expected_webauthn_secret);
  EXPECT_FALSE(session_->GetWebAuthnSecretHash().empty());
  // VERIFY

  // The second read should get nothing.
  EXPECT_EQ(session_->GetWebAuthnSecret(), nullptr);

  // The second read of the WebAuthn secret hash should still get the hash.
  EXPECT_FALSE(session_->GetWebAuthnSecretHash().empty());
}

// WebAuthn secret is cleared after timeout.
TEST_F(UserSessionTest, WebAuthnSecretTimeout) {
  // SETUP

  // Test with ecryptfs since it has a simpler existence check.
  CryptohomeVault::Options options = {
      .force_type = EncryptedContainerType::kEcryptfs,
  };

  EXPECT_CALL(*mount_,
              MountCryptohome(users_[0].name, _, VaultOptionsEqual(options)))
      .WillOnce(Return(MOUNT_ERROR_NONE));

  std::unique_ptr<VaultKeyset> vk = keyset_management_->GetValidKeyset(
      users_[0].credentials, nullptr /*error*/);
  EXPECT_EQ(MOUNT_ERROR_NONE,
            session_->MountVault(users_[0].name, FileSystemKeyset(*vk.get()),
                                 options));

  // TEST

  // TODO(b/184393647): Since GetWebAuthnSecret is not currently used yet,
  // the timer for clearing WebAuthn secret for security is minimized. It will
  // be set to appropriate duration after secret enforcement.
  task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(0));

  // VERIFY

  EXPECT_EQ(session_->GetWebAuthnSecret(), nullptr);

  // The WebAuthn secret hash will not be cleared after timeout.
  EXPECT_FALSE(session_->GetWebAuthnSecretHash().empty());
}

class UserSessionReAuthTest : public ::testing::Test {
 public:
  UserSessionReAuthTest() : salt() {}
  virtual ~UserSessionReAuthTest() {}

  // Not copyable or movable
  UserSessionReAuthTest(const UserSessionReAuthTest&) = delete;
  UserSessionReAuthTest& operator=(const UserSessionReAuthTest&) = delete;
  UserSessionReAuthTest(UserSessionReAuthTest&&) = delete;
  UserSessionReAuthTest& operator=(UserSessionReAuthTest&&) = delete;

  void SetUp() {
    salt.resize(16);
    GetSecureRandom(salt.data(), salt.size());
  }

 protected:
  SecureBlob salt;
};

TEST_F(UserSessionReAuthTest, VerifyUser) {
  Credentials credentials("username", SecureBlob("password"));
  scoped_refptr<UserSession> session =
      new UserSession(nullptr, nullptr, nullptr, nullptr, salt, nullptr);
  EXPECT_TRUE(session->SetCredentials(credentials));

  EXPECT_TRUE(session->VerifyUser(credentials.GetObfuscatedUsername(salt)));
  EXPECT_FALSE(session->VerifyUser("other"));
}

TEST_F(UserSessionReAuthTest, VerifyCredentials) {
  Credentials credentials_1("username", SecureBlob("password"));
  Credentials credentials_2("username", SecureBlob("password2"));
  Credentials credentials_3("username2", SecureBlob("password2"));

  scoped_refptr<UserSession> session =
      new UserSession(nullptr, nullptr, nullptr, nullptr, salt, nullptr);
  EXPECT_TRUE(session->SetCredentials(credentials_1));
  EXPECT_TRUE(session->VerifyCredentials(credentials_1));
  EXPECT_FALSE(session->VerifyCredentials(credentials_2));
  EXPECT_FALSE(session->VerifyCredentials(credentials_3));

  EXPECT_TRUE(session->SetCredentials(credentials_2));
  EXPECT_FALSE(session->VerifyCredentials(credentials_1));
  EXPECT_TRUE(session->VerifyCredentials(credentials_2));
  EXPECT_FALSE(session->VerifyCredentials(credentials_3));

  EXPECT_TRUE(session->SetCredentials(credentials_3));
  EXPECT_FALSE(session->VerifyCredentials(credentials_1));
  EXPECT_FALSE(session->VerifyCredentials(credentials_2));
  EXPECT_TRUE(session->VerifyCredentials(credentials_3));
}

}  // namespace cryptohome
