blob: 5e17283e672dca6d0ba2ac1ed5d179b88394ffcb [file] [log] [blame]
#include <sys/stat.h>
#include <string>
#include <fstream>
#include <experimental/filesystem>
#include <gtest/gtest.h>
#include <sdbusplus/bus.hpp>
#include "user.hpp"
namespace phosphor
{
namespace user
{
namespace fs = std::experimental::filesystem;
constexpr auto path = "/dummy/user";
constexpr auto testShadow = "/tmp/__tshadow__";
constexpr auto shadowCompare = "/tmp/__tshadowCompare__";
// New password
constexpr auto password = "passw0rd";
constexpr auto MD5 = "1";
constexpr auto SHA512 = "6";
constexpr auto salt = "1G.cK/YP";
// Example entry matching /etc/shadow structure
constexpr auto spPwdp = "$1$1G.cK/YP$JI5t0oliPxZveXOvLcZ/H.:17344:1:90:7:::";
class UserTest : public ::testing::Test
{
public:
const std::string md5Salt =
'$' + std::string(MD5) + '$' + std::string(salt) + '$';
const std::string shaSalt =
'$' + std::string(SHA512) + '$' + std::string(salt) + '$';
const std::string entry =
fs::path(path).filename().string() + ':' + std::string(spPwdp);
sdbusplus::bus::bus bus;
phosphor::user::User user;
// Gets called as part of each TEST_F construction
UserTest() : bus(sdbusplus::bus::new_default()), user(bus, path)
{
// Create a shadow file entry
std::ofstream file(testShadow);
file << entry;
file.close();
// File to compare against
std::ofstream compare(shadowCompare);
compare << entry;
compare.close();
}
// Gets called as part of each TEST_F destruction
~UserTest()
{
if (fs::exists(testShadow))
{
fs::remove(testShadow);
}
if (fs::exists(shadowCompare))
{
fs::remove(shadowCompare);
}
}
/** @brief wrapper for get crypt field */
auto getCryptField(char* data)
{
return User::getCryptField(std::forward<decltype(data)>(data));
}
/** @brief wrapper for getSaltString */
auto getSaltString(const std::string& crypt, const std::string& salt)
{
return User::getSaltString(std::forward<decltype(crypt)>(crypt),
std::forward<decltype(salt)>(salt));
}
/** @brief wrapper for generateHash */
auto generateHash(const std::string& password, const std::string& salt)
{
return User::generateHash(std::forward<decltype(password)>(password),
std::forward<decltype(salt)>(salt));
}
/** @brief Applies the new password */
auto applyPassword()
{
return user.applyPassword(testShadow, password, salt);
}
};
/** @brief Makes sure that SHA512 crypt field is extracted
*/
TEST_F(UserTest, sha512GetCryptField)
{
auto salt = const_cast<char*>(shaSalt.c_str());
EXPECT_EQ(SHA512, this->getCryptField(salt));
}
/** @brief Makes sure that MD5 crypt field is extracted as default
*/
TEST_F(UserTest, md55GetCryptFieldDefault)
{
auto salt = const_cast<char*>("hello");
EXPECT_EQ(MD5, this->getCryptField(salt));
}
/** @brief Makes sure that MD5 crypt field is extracted
*/
TEST_F(UserTest, md55GetCryptField)
{
auto salt = const_cast<char*>(md5Salt.c_str());
EXPECT_EQ(MD5, this->getCryptField(salt));
}
/** @brief Makes sure that salt string is put within $$
*/
TEST_F(UserTest, getSaltString)
{
EXPECT_EQ(md5Salt, this->getSaltString(MD5, salt));
}
/** @brief Makes sure hash is generated correctly
*/
TEST_F(UserTest, generateHash)
{
std::string sample = crypt(password, md5Salt.c_str());
std::string actual = generateHash(password, md5Salt);
EXPECT_EQ(sample, actual);
}
/** @brief Verifies that the correct password is written to file
*/
TEST_F(UserTest, applyPassword)
{
// Update the password
applyPassword();
// Read files and compare
std::ifstream shadow(testShadow);
std::ifstream copy(shadowCompare);
std::string shadowEntry;
shadow >> shadowEntry;
std::string shadowCompareEntry;
copy >> shadowCompareEntry;
EXPECT_EQ(shadowEntry, shadowCompareEntry);
}
/** @brief Verifies the permissions are correct
*/
TEST_F(UserTest, verifyShadowPermission)
{
// Change the permission to 400-> -r--------
chmod(testShadow, S_IRUSR);
chmod(shadowCompare, S_IRUSR);
// Update the password so that the temp file is in action
applyPassword();
// Compare the permission of 2 files.
// file rename would make sure that the permissions
// of old are moved to new
struct stat shadow
{
};
struct stat compare
{
};
stat(testShadow, &shadow);
stat(shadowCompare, &compare);
EXPECT_EQ(shadow.st_mode, compare.st_mode);
}
} // namespace user
} // namespace phosphor