diff options
author | Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com> | 2018-06-13 16:51:00 +0530 |
---|---|---|
committer | Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com> | 2018-10-09 03:19:19 +0530 |
commit | c704519ef29cf46473eddb670f311eead83c357d (patch) | |
tree | 2dc5357933c6756d5ebd3431e1a2143d871e4474 | |
parent | 9164fd9b15e7af88e8b80c7ed7dad45266327a57 (diff) | |
download | phosphor-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.cpp | 105 | ||||
-rw-r--r-- | user_mgr.hpp | 15 | ||||
-rw-r--r-- | users.cpp | 24 | ||||
-rw-r--r-- | users.hpp | 11 |
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; @@ -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 @@ -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; |