From c704519ef29cf46473eddb670f311eead83c357d Mon Sep 17 00:00:00 2001 From: Richard Marian Thomaiyar Date: Wed, 13 Jun 2018 16:51:00 +0530 Subject: Add support for user locked state property Support for user locked state property using pam_tally2 application added. Change-Id: Ia77ff6527c15c93ac272110950e99fff56dcbaa6 Signed-off-by: Richard Marian Thomaiyar Signed-off-by: Brad Bishop --- user_mgr.cpp | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 101 insertions(+), 4 deletions(-) (limited to 'user_mgr.cpp') diff --git a/user_mgr.cpp b/user_mgr.cpp index ee72b05..786a8fd 100644 --- a/user_mgr.cpp +++ b/user_mgr.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -82,18 +84,32 @@ using NoResource = using Argument = xyz::openbmc_project::Common::InvalidArgument; template -static void executeCmd(const char *path, ArgTypes &&... tArgs) +static std::vector executeCmd(const char *path, + ArgTypes &&... tArgs) { - boost::process::child execProg(path, const_cast(tArgs)...); + std::vector stdOutput; + boost::process::ipstream stdOutStream; + boost::process::child execProg(path, const_cast(tArgs)..., + boost::process::std_out > stdOutStream); + std::string stdOutLine; + + while (stdOutStream && std::getline(stdOutStream, stdOutLine) && + !stdOutLine.empty()) + { + stdOutput.emplace_back(stdOutLine); + } + execProg.wait(); + int retCode = execProg.exit_code(); if (retCode) { - log("Command execution failed", entry("PATH=%s", path), + log("Command execution failed", entry("PATH=%d", path), entry("RETURN_CODE:%d", retCode)); elog(); } - return; + + return stdOutput; } static std::string getCSVFromVector(std::vector vec) @@ -631,6 +647,87 @@ void UserMgr::userEnable(const std::string &userName, bool enabled) return; } +/** + * pam_tally2 app will provide the user failure count and failure status + * in second line of output with words position [0] - user name, + * [1] - failure count, [2] - latest timestamp, [3] - failure timestamp + * [4] - failure app + **/ + +static constexpr size_t t2UserIdx = 0; +static constexpr size_t t2FailCntIdx = 1; +static constexpr size_t t2OutputIndex = 1; + +bool UserMgr::userLockedForFailedAttempt(const std::string &userName) +{ + // All user management lock has to be based on /etc/shadow + phosphor::user::shadow::Lock lock(); + std::vector output; + + output = executeCmd("/usr/sbin/pam_tally2", "-u", userName.c_str()); + + std::vector splitWords; + boost::algorithm::split(splitWords, output[t2OutputIndex], + boost::algorithm::is_any_of("\t "), + boost::token_compress_on); + + if (splitWords[t2UserIdx] == userName) + { + try + { + unsigned long tmp = std::stoul(splitWords[t2FailCntIdx], nullptr); + uint16_t value16 = 0; + if (tmp > std::numeric_limits::max()) + { + throw std::out_of_range("Out of range"); + } + value16 = static_cast(tmp); + if (AccountPolicyIface::maxLoginAttemptBeforeLockout() != 0 && + value16 >= AccountPolicyIface::maxLoginAttemptBeforeLockout()) + { + return true; // User account is locked out + } + return false; // User account is un-locked + } + catch (const std::exception &e) + { + log("Exception for userLockedForFailedAttempt", + entry("WHAT=%s", e.what())); + throw e; + } + } + log("Unable to get user account failed attempt", + entry("USER_NAME=%s", userName.c_str())); + elog(); + return false; +} + +bool UserMgr::userLockedForFailedAttempt(const std::string &userName, + const bool &value) +{ + // All user management lock has to be based on /etc/shadow + phosphor::user::shadow::Lock lock(); + std::vector output; + if (value == true) + { + return userLockedForFailedAttempt(userName); + } + output = executeCmd("/usr/sbin/pam_tally2", "-u", userName.c_str(), "-r"); + + std::vector splitWords; + boost::algorithm::split(splitWords, output[t2OutputIndex], + boost::algorithm::is_any_of("\t "), + boost::token_compress_on); + + if (splitWords[t2UserIdx] == userName) + { + return userLockedForFailedAttempt(userName); + } + log("Unable to clear user account failed attempt"); + elog(); + return false; +} + UserSSHLists UserMgr::getUserAndSshGrpList() { // All user management lock has to be based on /etc/shadow -- cgit v1.2.1