From bdb298f744cc71421f0c2e6f50254f933c6bb3cc Mon Sep 17 00:00:00 2001 From: Vishwanatha Subbanna Date: Wed, 6 Sep 2017 11:39:22 +0530 Subject: Extract crypto algorithm field and add utility functions Password field of a user in /etc/shadow contains 3 parts: [Crypt algorithm, Salt, encrypted password] Example: A value of "1" in crypt algorithm maps to MD5 Need to use the same crypt algorithm that is already used before when the new password is to be updated. Change-Id: Ib7d8e0ad6f3bcce30f5c2be89b4e033230c07bf4 Signed-off-by: Vishwanatha Subbanna --- Makefile.am | 4 +++- user.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ user.hpp | 37 +++++++++++++++++++++++++++++++++++-- 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 +#include +#include +#include +#include #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 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 +#include +#include #include #include #include @@ -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; @@ -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 -- cgit v1.2.1