summaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--user_mgr.cpp105
-rw-r--r--user_mgr.hpp15
-rw-r--r--users.cpp24
-rw-r--r--users.hpp11
4 files changed, 151 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
diff --git a/user_mgr.hpp b/user_mgr.hpp
index b599724..c1673f1 100644
--- a/user_mgr.hpp
+++ b/user_mgr.hpp
@@ -126,6 +126,21 @@ class UserMgr : public UserMgrIface, AccountPolicyIface
*/
uint32_t accountUnlockTimeout(uint32_t val) override;
+ /** @brief lists user locked state for failed attempt
+ *
+ * @param[in] - user name
+ * @return - true / false indicating user locked / un-locked
+ **/
+ bool userLockedForFailedAttempt(const std::string &userName);
+
+ /** @brief lists user locked state for failed attempt
+ *
+ * @param[in]: user name
+ * @param[in]: value - false -unlock user account, true - no action taken
+ **/
+ bool userLockedForFailedAttempt(const std::string &userName,
+ const bool &value);
+
private:
/** @brief sdbusplus handler */
sdbusplus::bus::bus &bus;
diff --git a/users.cpp b/users.cpp
index c904916..84c401d 100644
--- a/users.cpp
+++ b/users.cpp
@@ -142,5 +142,29 @@ bool Users::userEnabled(bool value)
return UsersIface::userEnabled(value);
}
+/** @brief lists user locked state for failed attempt
+ *
+ **/
+bool Users::userLockedForFailedAttempt(void) const
+{
+ return manager.userLockedForFailedAttempt(userName);
+}
+
+/** @brief unlock user locked state for failed attempt
+ *
+ * @param[in]: value - false - unlock user account, true - no action taken
+ **/
+bool Users::userLockedForFailedAttempt(bool value)
+{
+ if (value != false)
+ {
+ return userLockedForFailedAttempt();
+ }
+ else
+ {
+ return manager.userLockedForFailedAttempt(userName, value);
+ }
+}
+
} // namespace user
} // namespace phosphor
diff --git a/users.hpp b/users.hpp
index 84a0f86..84a32f5 100644
--- a/users.hpp
+++ b/users.hpp
@@ -102,6 +102,17 @@ class Users : public UsersIface, DeleteIface
*/
bool userEnabled(bool value) override;
+ /** @brief lists user locked state for failed attempt
+ *
+ **/
+ bool userLockedForFailedAttempt(void) const override;
+
+ /** @brief unlock user locked state for failed attempt
+ *
+ * @param[in]: value - false - unlock user account, true - no action taken
+ **/
+ bool userLockedForFailedAttempt(bool value) override;
+
private:
std::string userName;
UserMgr &manager;
OpenPOWER on IntegriCloud