blob: 6282e7df2d1b5dfbd9fc302c1e5bd7f82cfd0cce [file] [log] [blame]
// Copyright 2019 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.
#include "cryptohome/userdataauth.h"
#include "cryptohome/mock_crypto.h"
#include "cryptohome/mock_homedirs.h"
#include "cryptohome/mock_mount.h"
#include "cryptohome/mock_platform.h"
#include "cryptohome/mock_tpm.h"
#include "cryptohome/mock_tpm_init.h"
using brillo::SecureBlob;
using ::testing::_;
using ::testing::Invoke;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::WithArgs;
namespace cryptohome {
namespace {
bool AssignSalt(size_t size, SecureBlob* salt) {
SecureBlob fake_salt(size, 'S');
salt->swap(fake_salt);
return true;
}
} // namespace
// UserDataAuthTestNotInitialized is a test fixture that does not call
// UserDataAuth::Initialize() during setup. Therefore, it's suited to tests that
// can be conducted without calling UserDataAuth::Initialize(), or for tests
// that wants some flexibility before calling UserDataAuth::Initialize(), note
// that in this case the test have to call UserDataAuth::Initialize().
class UserDataAuthTestNotInitialized : public ::testing::Test {
public:
UserDataAuthTestNotInitialized() = default;
~UserDataAuthTestNotInitialized() override = default;
void SetUp() override {
tpm_init_.set_tpm(&tpm_);
userdataauth_.set_crypto(&crypto_);
userdataauth_.set_homedirs(&homedirs_);
userdataauth_.set_tpm(&tpm_);
userdataauth_.set_tpm_init(&tpm_init_);
userdataauth_.set_platform(&platform_);
userdataauth_.set_disable_threading(true);
homedirs_.set_crypto(&crypto_);
homedirs_.set_platform(&platform_);
ON_CALL(homedirs_, Init(_, _, _)).WillByDefault(Return(true));
// Skip CleanUpStaleMounts by default.
ON_CALL(platform_, GetMountsBySourcePrefix(_, _))
.WillByDefault(Return(false));
// Setup fake salt by default.
ON_CALL(crypto_, GetOrCreateSalt(_, _, _, _))
.WillByDefault(WithArgs<1, 3>(Invoke(AssignSalt)));
}
// This is a utility function for tests to setup a mount for a particular
// user. After calling this function, |mount_| is available for use.
void SetupMount(const std::string& username) {
mount_ = new NiceMock<MockMount>();
userdataauth_.set_mount_for_user(username, mount_.get());
}
protected:
// Mock Crypto object, will be passed to UserDataAuth for its internal use.
NiceMock<MockCrypto> crypto_;
// Mock HomeDirs object, will be passed to UserDataAuth for its internal use.
NiceMock<MockHomeDirs> homedirs_;
// Mock Platform object, will be passed to UserDataAuth for its internal use.
NiceMock<MockPlatform> platform_;
// Mock TPM object, will be passed to UserDataAuth for its internal use.
NiceMock<MockTpm> tpm_;
// Mock TPM Init object, will be passed to UserDataAuth for its internal use.
NiceMock<MockTpmInit> tpm_init_;
// This is used to hold the mount object when we create a mock mount with
// SetupMount().
scoped_refptr<MockMount> mount_;
// Declare |userdataauth_| last so it gets destroyed before all the mocks.
// This is important because otherwise the background thread may call into
// mocks that have already been destroyed.
UserDataAuth userdataauth_;
private:
DISALLOW_COPY_AND_ASSIGN(UserDataAuthTestNotInitialized);
};
// Standard, fully initialized UserDataAuth test fixture
class UserDataAuthTest : public UserDataAuthTestNotInitialized {
public:
UserDataAuthTest() = default;
~UserDataAuthTest() override = default;
void SetUp() override {
UserDataAuthTestNotInitialized::SetUp();
ASSERT_TRUE(userdataauth_.Initialize());
}
private:
DISALLOW_COPY_AND_ASSIGN(UserDataAuthTest);
};
TEST_F(UserDataAuthTest, IsMounted) {
// By default there are no mount right after initialization
EXPECT_FALSE(userdataauth_.IsMounted());
EXPECT_FALSE(userdataauth_.IsMounted("foo@gmail.com"));
// Add a mount associated with foo@gmail.com
SetupMount("foo@gmail.com");
// Test the code path that doesn't specify a user, and when there's a mount
// that's unmounted.
EXPECT_CALL(*mount_, IsMounted()).WillOnce(Return(false));
EXPECT_FALSE(userdataauth_.IsMounted());
// Test to see if is_ephemeral works and test the code path that doesn't
// specify a user.
bool is_ephemeral = true;
EXPECT_CALL(*mount_, IsMounted()).WillOnce(Return(true));
EXPECT_CALL(*mount_, IsNonEphemeralMounted()).WillOnce(Return(true));
EXPECT_TRUE(userdataauth_.IsMounted("", &is_ephemeral));
EXPECT_FALSE(is_ephemeral);
// Test to see if is_ephemeral works, and test the code path that specify the
// user.
EXPECT_CALL(*mount_, IsMounted()).WillOnce(Return(true));
EXPECT_CALL(*mount_, IsNonEphemeralMounted()).WillOnce(Return(false));
EXPECT_TRUE(userdataauth_.IsMounted("foo@gmail.com", &is_ephemeral));
EXPECT_TRUE(is_ephemeral);
// Note: IsMounted will not be called in this case.
EXPECT_FALSE(userdataauth_.IsMounted("bar@gmail.com", &is_ephemeral));
EXPECT_FALSE(is_ephemeral);
}
} // namespace cryptohome