summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am4
-rw-r--r--user.cpp54
-rw-r--r--user.hpp37
3 files changed, 92 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am
index 472dd06..aebc8a2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,7 +7,9 @@ phosphor_user_manager_SOURCES = \
mainapp.cpp
phosphor_user_manager_LDFLAGS = $(SDBUSPLUS_LIBS) \
- $(PHOSPHOR_DBUS_INTERFACES_LIBS)
+ $(PHOSPHOR_DBUS_INTERFACES_LIBS) \
+ -lcrypt \
+ -lstdc++fs
phosphor_user_manager_CXXFLAGS = $(SYSTEMD_CFLAGS) \
$(PHOSPHOR_DBUS_INTERFACES_CFLAGS)
diff --git a/user.cpp b/user.cpp
index 0a6727b..f4b0e5e 100644
--- a/user.cpp
+++ b/user.cpp
@@ -13,16 +13,70 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <cstring>
+#include <unistd.h>
+#include <sys/types.h>
+#include <shadow.h>
+#include <array>
#include "user.hpp"
namespace phosphor
{
namespace user
{
+// Sets or updates the password
void User::setPassword(std::string newPassword)
{
+ // Needed by getspnam_r
+ struct spwd shdp;
+ struct spwd* pshdp;
+
+ // This should be fine even if SHA512 is used.
+ std::array<char,1024> buffer{};
+
+ // 1: Read /etc/shadow for the user
+ auto r = getspnam_r(user.c_str(), &shdp, buffer.data(),
+ buffer.max_size(), &pshdp);
+ if (r < 0)
+ {
+ return;
+ // TODO: Throw an error
+ }
+
+ // Done reading
+ endspent();
+
+ // 2: Parse and get crypt algo
+ auto cryptAlgo = getCryptField(shdp.sp_pwdp);
+ if (cryptAlgo.empty())
+ {
+ // TODO: Throw error getting crypt field
+ }
+
+ // TODO: Update the password in next commit
return;
}
+// Extract crypto algorithm field
+CryptAlgo User::getCryptField(char* spPwdp)
+{
+ char* savePtr{};
+ return strtok_r(spPwdp, "$", &savePtr);
+}
+
+// Returns specific format of salt string
+std::string User::getSaltString(const std::string& crypt,
+ const std::string& salt)
+{
+ return '$' + crypt + '$' + salt + '$';
+}
+
+// Given a password and salt, generates hash
+std::string User::generateHash(const std::string& password,
+ const std::string& salt)
+{
+ return crypt(password.c_str(), salt.c_str());
+}
+
} // namespace user
} // namespace phosphor
diff --git a/user.hpp b/user.hpp
index 25c7e62..aa40820 100644
--- a/user.hpp
+++ b/user.hpp
@@ -1,6 +1,7 @@
#pragma once
-#include <string>
+#include <cstring>
+#include <experimental/filesystem>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server/object.hpp>
#include <xyz/openbmc_project/User/Password/server.hpp>
@@ -9,6 +10,9 @@ namespace phosphor
namespace user
{
+using CryptAlgo = std::string;
+
+namespace fs = std::experimental::filesystem;
namespace Base = sdbusplus::xyz::openbmc_project::User::server;
using Interface = sdbusplus::server::object::object<Base::Password>;
@@ -35,7 +39,8 @@ class User : public Interface
User(sdbusplus::bus::bus& bus, const char* path)
: Interface(bus, path),
bus(bus),
- path(path)
+ path(path),
+ user(fs::path(path).filename())
{
// Do nothing
}
@@ -56,6 +61,34 @@ class User : public Interface
/** @brief object path */
const std::string& path;
+
+ /** @brief User id extracted from object path */
+ const std::string user;
+
+ /** @brief Extracts crypto number from the shadow entry for user
+ *
+ * @param[in] spPwdp - sp_pwdp of struct spwd
+ */
+ static CryptAlgo getCryptField(char* spPwdp);
+
+ /** @brief Generates one-way hash based on salt and password
+ *
+ * @param[in] password - clear text password
+ * @param[in] salt - Combination of crypto method and salt
+ * Eg: $1$HELLO$, where in 1 is crypto method
+ * and HELLO is salt
+ */
+ static std::string generateHash(const std::string& password,
+ const std::string& salt);
+
+ /** @brief returns salt string with $ delimiter.
+ * Eg: If crypt is 1 and salt is HELLO, returns $1$HELLO$
+ *
+ * @param[in] crypt - Crypt number in string
+ * @param[in] salt - salt
+ */
+ static std::string getSaltString(const std::string& crypt,
+ const std::string& salt);
};
} // namespace user
OpenPOWER on IntegriCloud