diff options
author | Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com> | 2017-09-06 11:39:22 +0530 |
---|---|---|
committer | Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com> | 2017-09-13 12:54:39 +0530 |
commit | bdb298f744cc71421f0c2e6f50254f933c6bb3cc (patch) | |
tree | 1505ad26fc8078c7fa6e0bd427d4e6f2ef9941c6 | |
parent | 54309f17f35169e9f4b617b98fec43f6ac6507e1 (diff) | |
download | phosphor-user-manager-bdb298f744cc71421f0c2e6f50254f933c6bb3cc.tar.gz phosphor-user-manager-bdb298f744cc71421f0c2e6f50254f933c6bb3cc.zip |
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 <vishwa@linux.vnet.ibm.com>
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | user.cpp | 54 | ||||
-rw-r--r-- | 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) @@ -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 @@ -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 |