summaryrefslogtreecommitdiff
path: root/special-mode-mgr/src/specialmodemgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'special-mode-mgr/src/specialmodemgr.cpp')
-rw-r--r--special-mode-mgr/src/specialmodemgr.cpp113
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)