blob: 5e17283e672dca6d0ba2ac1ed5d179b88394ffcb [file] [log] [blame]
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +05301#include <sys/stat.h>
2#include <string>
3#include <fstream>
4#include <experimental/filesystem>
5#include <gtest/gtest.h>
6#include <sdbusplus/bus.hpp>
7#include "user.hpp"
8namespace phosphor
9{
10namespace user
11{
12
13namespace fs = std::experimental::filesystem;
14
15constexpr auto path = "/dummy/user";
16constexpr auto testShadow = "/tmp/__tshadow__";
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +053017constexpr auto shadowCompare = "/tmp/__tshadowCompare__";
18
19// New password
20constexpr auto password = "passw0rd";
21
22constexpr auto MD5 = "1";
23constexpr auto SHA512 = "6";
24constexpr auto salt = "1G.cK/YP";
25
26// Example entry matching /etc/shadow structure
27constexpr auto spPwdp = "$1$1G.cK/YP$JI5t0oliPxZveXOvLcZ/H.:17344:1:90:7:::";
28
29class UserTest : public ::testing::Test
30{
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053031 public:
32 const std::string md5Salt =
33 '$' + std::string(MD5) + '$' + std::string(salt) + '$';
34 const std::string shaSalt =
35 '$' + std::string(SHA512) + '$' + std::string(salt) + '$';
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +053036
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053037 const std::string entry =
38 fs::path(path).filename().string() + ':' + std::string(spPwdp);
39 sdbusplus::bus::bus bus;
40 phosphor::user::User user;
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +053041
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053042 // Gets called as part of each TEST_F construction
43 UserTest() : bus(sdbusplus::bus::new_default()), user(bus, path)
44 {
45 // Create a shadow file entry
46 std::ofstream file(testShadow);
47 file << entry;
48 file.close();
49
50 // File to compare against
51 std::ofstream compare(shadowCompare);
52 compare << entry;
53 compare.close();
54 }
55
56 // Gets called as part of each TEST_F destruction
57 ~UserTest()
58 {
59 if (fs::exists(testShadow))
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +053060 {
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053061 fs::remove(testShadow);
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +053062 }
63
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053064 if (fs::exists(shadowCompare))
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +053065 {
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053066 fs::remove(shadowCompare);
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +053067 }
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053068 }
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +053069
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053070 /** @brief wrapper for get crypt field */
71 auto getCryptField(char* data)
72 {
73 return User::getCryptField(std::forward<decltype(data)>(data));
74 }
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +053075
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053076 /** @brief wrapper for getSaltString */
77 auto getSaltString(const std::string& crypt, const std::string& salt)
78 {
79 return User::getSaltString(std::forward<decltype(crypt)>(crypt),
80 std::forward<decltype(salt)>(salt));
81 }
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +053082
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053083 /** @brief wrapper for generateHash */
84 auto generateHash(const std::string& password, const std::string& salt)
85 {
86 return User::generateHash(std::forward<decltype(password)>(password),
87 std::forward<decltype(salt)>(salt));
88 }
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +053089
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +053090 /** @brief Applies the new password */
91 auto applyPassword()
92 {
93 return user.applyPassword(testShadow, password, salt);
94 }
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +053095};
96
97/** @brief Makes sure that SHA512 crypt field is extracted
98 */
99TEST_F(UserTest, sha512GetCryptField)
100{
101 auto salt = const_cast<char*>(shaSalt.c_str());
102 EXPECT_EQ(SHA512, this->getCryptField(salt));
103}
104
105/** @brief Makes sure that MD5 crypt field is extracted as default
106 */
107TEST_F(UserTest, md55GetCryptFieldDefault)
108{
109 auto salt = const_cast<char*>("hello");
110 EXPECT_EQ(MD5, this->getCryptField(salt));
111}
112
113/** @brief Makes sure that MD5 crypt field is extracted
114 */
115TEST_F(UserTest, md55GetCryptField)
116{
117 auto salt = const_cast<char*>(md5Salt.c_str());
118 EXPECT_EQ(MD5, this->getCryptField(salt));
119}
120
121/** @brief Makes sure that salt string is put within $$
122 */
123TEST_F(UserTest, getSaltString)
124{
125 EXPECT_EQ(md5Salt, this->getSaltString(MD5, salt));
126}
127
128/** @brief Makes sure hash is generated correctly
129 */
130TEST_F(UserTest, generateHash)
131{
132 std::string sample = crypt(password, md5Salt.c_str());
133 std::string actual = generateHash(password, md5Salt);
134 EXPECT_EQ(sample, actual);
135}
136
137/** @brief Verifies that the correct password is written to file
138 */
139TEST_F(UserTest, applyPassword)
140{
141 // Update the password
142 applyPassword();
143
144 // Read files and compare
145 std::ifstream shadow(testShadow);
146 std::ifstream copy(shadowCompare);
147
148 std::string shadowEntry;
149 shadow >> shadowEntry;
150
151 std::string shadowCompareEntry;
152 copy >> shadowCompareEntry;
153
154 EXPECT_EQ(shadowEntry, shadowCompareEntry);
155}
156
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +0530157/** @brief Verifies the permissions are correct
158 */
159TEST_F(UserTest, verifyShadowPermission)
160{
161 // Change the permission to 400-> -r--------
162 chmod(testShadow, S_IRUSR);
163 chmod(shadowCompare, S_IRUSR);
164
165 // Update the password so that the temp file is in action
166 applyPassword();
167
168 // Compare the permission of 2 files.
169 // file rename would make sure that the permissions
170 // of old are moved to new
Richard Marian Thomaiyar9f630d92018-05-24 10:49:10 +0530171 struct stat shadow
172 {
173 };
174 struct stat compare
175 {
176 };
Vishwanatha Subbanna035a9692017-09-15 18:50:43 +0530177
178 stat(testShadow, &shadow);
179 stat(shadowCompare, &compare);
180 EXPECT_EQ(shadow.st_mode, compare.st_mode);
181}
182
183} // namespace user
184} // namespace phosphor