summaryrefslogtreecommitdiffstats
path: root/user_mgr.cpp
diff options
context:
space:
mode:
authorRichard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>2018-06-13 16:51:00 +0530
committerRichard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>2018-10-09 03:19:19 +0530
commitc704519ef29cf46473eddb670f311eead83c357d (patch)
tree2dc5357933c6756d5ebd3431e1a2143d871e4474 /user_mgr.cpp
parent9164fd9b15e7af88e8b80c7ed7dad45266327a57 (diff)
downloadphosphor-user-manager-c704519ef29cf46473eddb670f311eead83c357d.tar.gz
phosphor-user-manager-c704519ef29cf46473eddb670f311eead83c357d.zip
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 <richard.marian.thomaiyar@linux.intel.com> Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
Diffstat (limited to 'user_mgr.cpp')
-rw-r--r--user_mgr.cpp105
1 files changed, 101 insertions, 4 deletions
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 <algorithm>
#include <numeric>
#include <boost/process/child.hpp>
+#include <boost/process/io.hpp>
+#include <boost/algorithm/string/split.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
#include <xyz/openbmc_project/User/Common/error.hpp>
#include <phosphor-logging/log.hpp>
@@ -82,18 +84,32 @@ using NoResource =
using Argument = xyz::openbmc_project::Common::InvalidArgument;
template <typename... ArgTypes>
-static void executeCmd(const char *path, ArgTypes &&... tArgs)
+static std::vector<std::string> executeCmd(const char *path,
+ ArgTypes &&... tArgs)
{
- boost::process::child execProg(path, const_cast<char *>(tArgs)...);
+ std::vector<std::string> stdOutput;
+ boost::process::ipstream stdOutStream;
+ boost::process::child execProg(path, const_cast<char *>(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<level::ERR>("Command execution failed", entry("PATH=%s", path),
+ log<level::ERR>("Command execution failed", entry("PATH=%d", path),
entry("RETURN_CODE:%d", retCode));
elog<InternalFailure>();
}
- return;
+
+ return stdOutput;
}
static std::string getCSVFromVector(std::vector<std::string> 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<std::string> output;
+
+ output = executeCmd("/usr/sbin/pam_tally2", "-u", userName.c_str());
+
+ std::vector<std::string> 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<decltype(value16)>::max())
+ {
+ throw std::out_of_range("Out of range");
+ }
+ value16 = static_cast<decltype(value16)>(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<level::ERR>("Exception for userLockedForFailedAttempt",
+ entry("WHAT=%s", e.what()));
+ throw e;
+ }
+ }
+ log<level::ERR>("Unable to get user account failed attempt",
+ entry("USER_NAME=%s", userName.c_str()));
+ elog<InternalFailure>();
+ 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<std::string> output;
+ if (value == true)
+ {
+ return userLockedForFailedAttempt(userName);
+ }
+ output = executeCmd("/usr/sbin/pam_tally2", "-u", userName.c_str(), "-r");
+
+ std::vector<std::string> 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<level::ERR>("Unable to clear user account failed attempt");
+ elog<InternalFailure>();
+ return false;
+}
+
UserSSHLists UserMgr::getUserAndSshGrpList()
{
// All user management lock has to be based on /etc/shadow
OpenPOWER on IntegriCloud