diff options
Diffstat (limited to 'special-mode-mgr/src/specialmodemgr.cpp')
-rw-r--r-- | special-mode-mgr/src/specialmodemgr.cpp | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/special-mode-mgr/src/specialmodemgr.cpp b/special-mode-mgr/src/specialmodemgr.cpp index 132b26e..61c1d8a 100644 --- a/special-mode-mgr/src/specialmodemgr.cpp +++ b/special-mode-mgr/src/specialmodemgr.cpp @@ -15,9 +15,13 @@ */ #include "specialmodemgr.hpp" +#include "file.hpp" +#include <security/pam_appl.h> #include <sys/sysinfo.h> +#include <pwd.h> +#include <shadow.h> #include <fstream> #include <phosphor-logging/log.hpp> #include <string> @@ -46,6 +50,112 @@ using VariantValue = namespace secCtrl = sdbusplus::xyz::openbmc_project::Control::Security::server; +#ifdef BMC_VALIDATION_UNSECURE_FEATURE + +static int pamFunctionConversation(int numMsg, const struct pam_message** msg, + struct pam_response** resp, void* appdataPtr) +{ + if (appdataPtr == nullptr) + { + return PAM_AUTH_ERR; + } + size_t passSize = std::strlen(reinterpret_cast<char*>(appdataPtr)) + 1; + char* pass = reinterpret_cast<char*>(malloc(passSize)); + std::strncpy(pass, reinterpret_cast<char*>(appdataPtr), passSize); + + *resp = reinterpret_cast<pam_response*>( + calloc(numMsg, sizeof(struct pam_response))); + + for (int i = 0; i < numMsg; ++i) + { + if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF) + { + continue; + } + resp[i]->resp = pass; + } + return PAM_SUCCESS; +} + +int pamUpdatePasswd(const char* username, const char* password) +{ + const struct pam_conv localConversation = {pamFunctionConversation, + const_cast<char*>(password)}; + pam_handle_t* localAuthHandle = NULL; // this gets set by pam_start + + int retval = + pam_start("passwd", username, &localConversation, &localAuthHandle); + + if (retval != PAM_SUCCESS) + { + return retval; + } + + retval = pam_chauthtok(localAuthHandle, PAM_SILENT); + if (retval != PAM_SUCCESS) + { + pam_end(localAuthHandle, retval); + return retval; + } + + return pam_end(localAuthHandle, PAM_SUCCESS); +} + +static void checkAndConfigureSpecialUser() +{ + std::array<char, 4096> sbuffer{}; + struct spwd spwd; + struct spwd* resultPtr = nullptr; + constexpr const char* specialUser = "root"; + constexpr const char* specialUserDefPasswd = "0penBmc1"; + + // Query shadow entry for special user. + int status = getspnam_r(specialUser, &spwd, sbuffer.data(), + sbuffer.max_size(), &resultPtr); + if (status || (&spwd != resultPtr)) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "Error in querying shadow entry for special user"); + } + // Encrypted Password may be NULL or single character '!' if user is + // disabled + if (resultPtr->sp_pwdp[0] == 0 || resultPtr->sp_pwdp[1] == 0) + { + pamUpdatePasswd(specialUser, specialUserDefPasswd); + // requery the special user shadow entry as there is password + // update. + resultPtr = nullptr; + status = getspnam_r(specialUser, &spwd, sbuffer.data(), + sbuffer.max_size(), &resultPtr); + if (status || (&spwd != resultPtr)) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "Error in querying shadow entry for special user"); + } + // Mark the password as expired to force update the password + File passwdFd("/etc/shadow", "r+"); + if ((passwdFd)() == nullptr) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "Error in opening shadow file"); + return; + } + // Mark the special user password as expired. This will + // force the user to set new password on first login. + resultPtr->sp_lstchg = 0; + putspent(resultPtr, (passwdFd)()); + phosphor::logging::log<phosphor::logging::level::INFO>( + "Configured special user sucessfully"); + } + else + { + phosphor::logging::log<phosphor::logging::level::DEBUG>( + "Skip configuring special user as it is already enabled"); + } +} + +#endif + SpecialModeMgr::SpecialModeMgr( boost::asio::io_service& io_, sdbusplus::asio::object_server& srv_, std::shared_ptr<sdbusplus::asio::connection>& conn_) : @@ -192,6 +302,9 @@ void SpecialModeMgr::checkAndAddSpecialModeProperty(const std::string& provMode) sd_journal_send("MESSAGE=%s", "Manufacturing mode - Entered", "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s", "OpenBMC.0.1.ManufacturingModeEntered", NULL); +#ifdef BMC_VALIDATION_UNSECURE_FEATURE + checkAndConfigureSpecialUser(); +#endif } addSpecialModeProperty(); if (!specialModeLockoutSeconds) |