summaryrefslogtreecommitdiffstats
path: root/user_channel
diff options
context:
space:
mode:
authorAppaRao Puli <apparao.puli@intel.com>2018-05-17 10:28:48 +0530
committerRichard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>2018-11-13 11:26:09 +0530
commitb29b5ab3b9ad812949f3621a4422fde8d7c1c8d2 (patch)
treee25e81565b04c8513af25e3ad7376a03a685cdbb /user_channel
parent4654d99fda30800024c56b085ec9dcf2ac26c417 (diff)
downloadphosphor-host-ipmid-b29b5ab3b9ad812949f3621a4422fde8d7c1c8d2.tar.gz
phosphor-host-ipmid-b29b5ab3b9ad812949f3621a4422fde8d7c1c8d2.zip
Handling delete password entry from ipmi-pass
API to Handle the delete password entry from ipmi-pass encrypted file when user gets deleted by any interface Change-Id: I692a81b166b53d6fc981fdb85ce5d6980887560b Signed-off-by: AppaRao Puli <apparao.puli@intel.com> Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
Diffstat (limited to 'user_channel')
-rw-r--r--user_channel/file.hpp88
-rw-r--r--user_channel/passwd_mgr.cpp446
-rw-r--r--user_channel/passwd_mgr.hpp45
-rw-r--r--user_channel/user_layer.cpp6
-rw-r--r--user_channel/user_layer.hpp9
5 files changed, 518 insertions, 76 deletions
diff --git a/user_channel/file.hpp b/user_channel/file.hpp
new file mode 100644
index 0000000..2c537b1
--- /dev/null
+++ b/user_channel/file.hpp
@@ -0,0 +1,88 @@
+#pragma once
+
+#include <stdio.h>
+
+#include <experimental/filesystem>
+namespace phosphor
+{
+namespace user
+{
+
+namespace fs = std::experimental::filesystem;
+
+/** @class File
+ * @brief Responsible for handling file pointer
+ * Needed by putspent(3)
+ */
+class File
+{
+ private:
+ /** @brief handler for operating on file */
+ FILE* fp = NULL;
+
+ /** @brief File name. Needed in the case where the temp
+ * needs to be removed
+ */
+ const std::string& name;
+
+ /** @brief Should the file be removed at exit */
+ bool removeOnExit = false;
+
+ public:
+ File() = delete;
+ File(const File&) = delete;
+ File& operator=(const File&) = delete;
+ File(File&&) = delete;
+ File& operator=(File&&) = delete;
+
+ /** @brief Opens file and uses it to do file operation
+ *
+ * @param[in] name - File name
+ * @param[in] mode - File open mode
+ * @param[in] removeOnExit - File to be removed at exit or no
+ */
+ File(const std::string& name, const std::string& mode,
+ bool removeOnExit = false) :
+ name(name),
+ removeOnExit(removeOnExit)
+ {
+ fp = fopen(name.c_str(), mode.c_str());
+ }
+
+ /** @brief Opens file using provided file descriptor
+ *
+ * @param[in] fd - File descriptor
+ * @param[in] name - File name
+ * @param[in] mode - File open mode
+ * @param[in] removeOnExit - File to be removed at exit or no
+ */
+ File(int fd, const std::string& name, const std::string& mode,
+ bool removeOnExit = false) :
+ name(name),
+ removeOnExit(removeOnExit)
+ {
+ fp = fdopen(fd, mode.c_str());
+ }
+
+ ~File()
+ {
+ if (fp)
+ {
+ fclose(fp);
+ }
+
+ // Needed for exception safety
+ if (removeOnExit && fs::exists(name))
+ {
+ fs::remove(name);
+ }
+ }
+
+ auto operator()()
+ {
+ return fp;
+ }
+};
+
+} // namespace user
+} // namespace phosphor
diff --git a/user_channel/passwd_mgr.cpp b/user_channel/passwd_mgr.cpp
index 1d8a1ce..15e6e34 100644
--- a/user_channel/passwd_mgr.cpp
+++ b/user_channel/passwd_mgr.cpp
@@ -16,15 +16,20 @@
#include "passwd_mgr.hpp"
+#include "file.hpp"
#include "shadowlock.hpp"
#include <openssl/hmac.h>
+#include <openssl/rand.h>
#include <openssl/sha.h>
#include <string.h>
#include <sys/stat.h>
+#include <unistd.h>
+#include <cerrno>
#include <cstring>
#include <fstream>
+#include <iomanip>
#include <phosphor-logging/log.hpp>
namespace ipmi
@@ -34,7 +39,12 @@ static const char* passwdFileName = "/etc/ipmi_pass";
static const char* encryptKeyFileName = "/etc/key_file";
static const size_t maxKeySize = 8;
-static const char* META_PASSWD_SIG = "=OPENBMC=";
+#define META_PASSWD_SIG "=OPENBMC="
+
+static inline size_t blockRound(size_t odd, size_t blk)
+{
+ return ((odd) + (((blk) - ((odd) & ((blk)-1))) & ((blk)-1)));
+}
/*
* Meta data struct for encrypted password file
@@ -68,16 +78,36 @@ std::string PasswdMgr::getPasswdByUserName(const std::string& userName)
return iter->second;
}
-void PasswdMgr::checkAndReload(void)
+int PasswdMgr::clearUserEntry(const std::string& userName)
{
- struct stat fileStat = {};
- if (stat(passwdFileName, &fileStat) != 0)
+ std::time_t updatedTime = getUpdatedFileTime();
+ // Check file time stamp to know passwdMapList is up-to-date.
+ // If not up-to-date, then updatePasswdSpecialFile will read and
+ // check the user entry existance.
+ if (fileLastUpdatedTime == updatedTime && updatedTime != -EIO)
{
- log<level::DEBUG>("Error in getting last updated time stamp");
- return;
+ if (passwdMapList.find(userName) == passwdMapList.end())
+ {
+ log<level::DEBUG>("User not found");
+ return 0;
+ }
}
- std::time_t updatedTime = fileStat.st_mtime;
- if (fileLastUpdatedTime != updatedTime)
+
+ // Write passwdMap to Encryted file
+ if (updatePasswdSpecialFile(userName) != 0)
+ {
+ log<level::DEBUG>("Passwd file update failed");
+ return -EIO;
+ }
+
+ log<level::DEBUG>("Passwd file updated successfully");
+ return 0;
+}
+
+void PasswdMgr::checkAndReload(void)
+{
+ std::time_t updatedTime = getUpdatedFileTime();
+ if (fileLastUpdatedTime != updatedTime && updatedTime != -1)
{
log<level::DEBUG>("Reloading password map list");
passwdMapList.clear();
@@ -85,49 +115,55 @@ void PasswdMgr::checkAndReload(void)
}
}
-int PasswdMgr::decrypt(const EVP_CIPHER* cipher, uint8_t* key, size_t keyLen,
- uint8_t* iv, size_t ivLen, uint8_t* inBytes,
- size_t inBytesLen, uint8_t* mac, size_t macLen,
- uint8_t* outBytes, size_t* outBytesLen)
+int PasswdMgr::encryptDecryptData(bool doEncrypt, const EVP_CIPHER* cipher,
+ uint8_t* key, size_t keyLen, uint8_t* iv,
+ size_t ivLen, uint8_t* inBytes,
+ size_t inBytesLen, uint8_t* mac,
+ size_t* macLen, unsigned char* outBytes,
+ size_t* outBytesLen)
{
-
if (cipher == NULL || key == NULL || iv == NULL || inBytes == NULL ||
outBytes == NULL || mac == NULL || inBytesLen == 0 ||
(size_t)EVP_CIPHER_key_length(cipher) > keyLen ||
(size_t)EVP_CIPHER_iv_length(cipher) > ivLen)
{
log<level::DEBUG>("Error Invalid Inputs");
- return -1;
+ return -EINVAL;
}
- std::array<uint8_t, EVP_MAX_MD_SIZE> calMac;
- size_t calMacLen = calMac.size();
- // calculate MAC for the encrypted message.
- if (NULL == HMAC(EVP_sha256(), key, keyLen, inBytes, inBytesLen,
- calMac.data(),
- reinterpret_cast<unsigned int*>(&calMacLen)))
+ if (!doEncrypt)
{
- log<level::DEBUG>("Error: Failed to calculate MAC");
- return -1;
- }
- if (!((calMacLen == macLen) &&
- (std::memcmp(calMac.data(), mac, calMacLen) == 0)))
- {
- log<level::DEBUG>("Authenticated message doesn't match");
- return -1;
+ // verify MAC before decrypting the data.
+ std::array<uint8_t, EVP_MAX_MD_SIZE> calMac;
+ size_t calMacLen = calMac.size();
+ // calculate MAC for the encrypted message.
+ if (NULL == HMAC(EVP_sha256(), key, keyLen, inBytes, inBytesLen,
+ calMac.data(),
+ reinterpret_cast<unsigned int*>(&calMacLen)))
+ {
+ log<level::DEBUG>("Error: Failed to calculate MAC");
+ return -EIO;
+ }
+ if (!((calMacLen == *macLen) &&
+ (std::memcmp(calMac.data(), mac, calMacLen) == 0)))
+ {
+ log<level::DEBUG>("Authenticated message doesn't match");
+ return -EBADMSG;
+ }
}
std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)> ctx(
EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);
EVP_CIPHER_CTX_set_padding(ctx.get(), 1);
- // Set key & IV to decrypt
- int retval = EVP_CipherInit_ex(ctx.get(), cipher, NULL, key, iv, 0);
+ // Set key & IV
+ int retval = EVP_CipherInit_ex(ctx.get(), cipher, NULL, key, iv,
+ static_cast<int>(doEncrypt));
if (!retval)
{
log<level::DEBUG>("EVP_CipherInit_ex failed",
entry("RET_VAL=%d", retval));
- return -1;
+ return -EIO;
}
int outLen = 0, outEVPLen = 0;
@@ -145,14 +181,25 @@ int PasswdMgr::decrypt(const EVP_CIPHER* cipher, uint8_t* key, size_t keyLen,
{
log<level::DEBUG>("EVP_CipherFinal fails",
entry("RET_VAL=%d", retval));
- return -1;
+ return -EIO;
}
}
else
{
log<level::DEBUG>("EVP_CipherUpdate fails",
entry("RET_VAL=%d", retval));
- return -1;
+ return -EIO;
+ }
+
+ if (doEncrypt)
+ {
+ // Create MAC for the encrypted message
+ if (NULL == HMAC(EVP_sha256(), key, keyLen, outBytes, *outBytesLen, mac,
+ reinterpret_cast<unsigned int*>(macLen)))
+ {
+ log<level::DEBUG>("Failed to create authentication");
+ return -EIO;
+ }
}
return 0;
}
@@ -160,39 +207,73 @@ int PasswdMgr::decrypt(const EVP_CIPHER* cipher, uint8_t* key, size_t keyLen,
void PasswdMgr::initPasswordMap(void)
{
phosphor::user::shadow::Lock lock();
+ std::vector<uint8_t> dataBuf;
+ if (readPasswdFileData(dataBuf) != 0)
+ {
+ log<level::DEBUG>("Error in reading the encrypted pass file");
+ return;
+ }
+
+ if (dataBuf.size() != 0)
+ {
+ // populate the user list with password
+ char* outPtr = reinterpret_cast<char*>(dataBuf.data());
+ char* nToken = NULL;
+ char* linePtr = strtok_r(outPtr, "\n", &nToken);
+ size_t userEPos = 0, lineSize = 0;
+ while (linePtr != NULL)
+ {
+ std::string lineStr(linePtr);
+ if ((userEPos = lineStr.find(":")) != std::string::npos)
+ {
+ lineSize = lineStr.size();
+ passwdMapList.emplace(
+ lineStr.substr(0, userEPos),
+ lineStr.substr(userEPos + 1, lineSize - (userEPos + 1)));
+ }
+ linePtr = strtok_r(NULL, "\n", &nToken);
+ }
+ }
+
+ // Update the timestamp
+ fileLastUpdatedTime = getUpdatedFileTime();
+ return;
+}
+
+int PasswdMgr::readPasswdFileData(std::vector<uint8_t>& outBytes)
+{
std::array<uint8_t, maxKeySize> keyBuff;
std::ifstream keyFile(encryptKeyFileName, std::ios::in | std::ios::binary);
if (!keyFile.is_open())
{
log<level::DEBUG>("Error in opening encryption key file");
- return;
+ return -EIO;
}
- keyFile.read((char*)keyBuff.data(), keyBuff.size());
+ keyFile.read(reinterpret_cast<char*>(keyBuff.data()), keyBuff.size());
if (keyFile.fail())
{
log<level::DEBUG>("Error in reading encryption key file");
- return;
+ return -EIO;
}
std::ifstream passwdFile(passwdFileName, std::ios::in | std::ios::binary);
if (!passwdFile.is_open())
{
log<level::DEBUG>("Error in opening ipmi password file");
- return;
+ return -EIO;
}
// calculate file size and read the data
- std::vector<uint8_t> input;
passwdFile.seekg(0, std::ios::end);
ssize_t fileSize = passwdFile.tellg();
passwdFile.seekg(0, std::ios::beg);
- input.resize(fileSize);
- passwdFile.read((char*)input.data(), fileSize);
+ std::vector<uint8_t> input(fileSize);
+ passwdFile.read(reinterpret_cast<char*>(input.data()), fileSize);
if (passwdFile.fail())
{
log<level::DEBUG>("Error in reading encryption key file");
- return;
+ return -EIO;
}
// verify the signature first
@@ -201,61 +282,286 @@ void PasswdMgr::initPasswordMap(void)
sizeof(metaData->signature)))
{
log<level::DEBUG>("Error signature mismatch in password file");
- return;
+ return -EBADMSG;
+ }
+
+ size_t inBytesLen = metaData->dataSize + metaData->padSize;
+ // If data is empty i.e no password map then return success
+ if (inBytesLen == 0)
+ {
+ log<level::DEBUG>("Empty password file");
+ return 0;
}
// compute the key needed to decrypt
std::array<uint8_t, EVP_MAX_KEY_LENGTH> key;
auto keyLen = key.size();
- HMAC(EVP_sha256(), keyBuff.data(), keyBuff.size(),
- input.data() + sizeof(*metaData), metaData->hashSize, key.data(),
- reinterpret_cast<unsigned int*>(&keyLen));
+ if (NULL == HMAC(EVP_sha256(), keyBuff.data(), keyBuff.size(),
+ input.data() + sizeof(*metaData), metaData->hashSize,
+ key.data(), reinterpret_cast<unsigned int*>(&keyLen)))
+ {
+ log<level::DEBUG>("Failed to create MAC for authentication");
+ return -EIO;
+ }
// decrypt the data
uint8_t* iv = input.data() + sizeof(*metaData) + metaData->hashSize;
size_t ivLen = metaData->ivSize;
uint8_t* inBytes = iv + ivLen;
- size_t inBytesLen = metaData->dataSize + metaData->padSize;
uint8_t* mac = inBytes + inBytesLen;
size_t macLen = metaData->macSize;
- std::vector<uint8_t> outBytes(inBytesLen + EVP_MAX_BLOCK_LENGTH);
- size_t outBytesLen = outBytes.size();
- if (decrypt(EVP_aes_128_cbc(), key.data(), keyLen, iv, ivLen, inBytes,
- inBytesLen, mac, macLen, outBytes.data(), &outBytesLen) != 0)
+
+ size_t outBytesLen = 0;
+ // Resize to actual data size
+ outBytes.resize(inBytesLen + EVP_MAX_BLOCK_LENGTH);
+ if (encryptDecryptData(false, EVP_aes_128_cbc(), key.data(), keyLen, iv,
+ ivLen, inBytes, inBytesLen, mac, &macLen,
+ outBytes.data(), &outBytesLen) != 0)
{
log<level::DEBUG>("Error in decryption");
- return;
+ return -EIO;
}
- outBytes[outBytesLen] = 0;
+ // Resize the vector to outBytesLen
+ outBytes.resize(outBytesLen);
+
OPENSSL_cleanse(key.data(), keyLen);
OPENSSL_cleanse(iv, ivLen);
- // populate the user list with password
- char* outPtr = reinterpret_cast<char*>(outBytes.data());
- char* nToken = NULL;
- char* linePtr = strtok_r(outPtr, "\n", &nToken);
- size_t userEPos = 0, lineSize = 0;
- while (linePtr != NULL)
+ return 0;
+}
+
+int PasswdMgr::updatePasswdSpecialFile(const std::string& userName)
+{
+ phosphor::user::shadow::Lock lock();
+
+ size_t bytesWritten = 0;
+ size_t inBytesLen = 0;
+ size_t isUsrFound = false;
+ const EVP_CIPHER* cipher = EVP_aes_128_cbc();
+ std::vector<uint8_t> dataBuf;
+
+ // Read the encrypted file and get the file data
+ // Check user existance and return if not exist.
+ if (readPasswdFileData(dataBuf) != 0)
+ {
+ log<level::DEBUG>("Error in reading the encrypted pass file");
+ return -EIO;
+ }
+
+ if (dataBuf.size() != 0)
+ {
+ inBytesLen = dataBuf.size() + EVP_CIPHER_block_size(cipher);
+ }
+
+ std::vector<uint8_t> inBytes(inBytesLen);
+ if (inBytesLen != 0)
{
- std::string lineStr(linePtr);
- if ((userEPos = lineStr.find(":")) != std::string::npos)
+ char* outPtr = reinterpret_cast<char*>(dataBuf.data());
+ size_t userEPos = 0;
+ char* nToken = NULL;
+ char* linePtr = strtok_r(outPtr, "\n", &nToken);
+ while (linePtr != NULL)
{
- lineSize = lineStr.size();
- passwdMapList.emplace(
- lineStr.substr(0, userEPos),
- lineStr.substr(userEPos + 1, lineSize - (userEPos + 1)));
+ std::string lineStr(linePtr);
+ if ((userEPos = lineStr.find(":")) != std::string::npos)
+ {
+ if (userName.compare(lineStr.substr(0, userEPos)) == 0)
+ {
+ isUsrFound = true;
+ }
+ else
+ {
+ bytesWritten += std::snprintf(
+ reinterpret_cast<char*>(&inBytes[0]) + bytesWritten,
+ inBytesLen, "%s\n", lineStr.data());
+ }
+ }
+ linePtr = strtok_r(NULL, "\n", &nToken);
}
- linePtr = strtok_r(NULL, "\n", &nToken);
+
+ // Round of to block size and padding remaing bytes with zero.
+ inBytesLen = blockRound(bytesWritten, EVP_CIPHER_block_size(cipher));
+ std::memset(&inBytes[0] + bytesWritten, 0, inBytesLen - bytesWritten);
}
- // Update the timestamp
+ if (!isUsrFound)
+ {
+ log<level::DEBUG>("User doesn't exist");
+ return 0;
+ }
+
+ // Read the key buff from key file
+ std::array<uint8_t, maxKeySize> keyBuff;
+ std::ifstream keyFile(encryptKeyFileName, std::ios::in | std::ios::binary);
+ if (!keyFile.good())
+ {
+ log<level::DEBUG>("Error in opening encryption key file");
+ return -EIO;
+ }
+ keyFile.read(reinterpret_cast<char*>(keyBuff.data()), keyBuff.size());
+ if (keyFile.fail())
+ {
+ log<level::DEBUG>("Error in reading encryption key file");
+ return -EIO;
+ }
+ keyFile.close();
+
+ // Read the original passwd file mode
+ struct stat st = {};
+ if (stat(passwdFileName, &st) != 0)
+ {
+ log<level::DEBUG>("Error in getting password file fstat()");
+ return -EIO;
+ }
+
+ // Create temporary file for write
+ std::string pwdFile(passwdFileName);
+ std::vector<char> tempFileName(pwdFile.begin(), pwdFile.end());
+ std::vector<char> fileTemplate = {'_', '_', 'X', 'X', 'X',
+ 'X', 'X', 'X', '\0'};
+ tempFileName.insert(tempFileName.end(), fileTemplate.begin(),
+ fileTemplate.end());
+ int fd = mkstemp((char*)tempFileName.data());
+ if (fd == -1)
+ {
+ log<level::DEBUG>("Error creating temp file");
+ return -EIO;
+ }
+
+ std::string strTempFileName(tempFileName.data());
+ // Open the temp file for writing from provided fd
+ // By "true", remove it at exit if still there.
+ // This is needed to cleanup the temp file at exception
+ phosphor::user::File temp(fd, strTempFileName, "w", true);
+ if ((temp)() == NULL)
+ {
+ close(fd);
+ log<level::DEBUG>("Error creating temp file");
+ return -EIO;
+ }
+ fd = -1; // don't use fd anymore, as the File object owns it
+
+ // Set the file mode as of actual ipmi-pass file.
+ if (fchmod(fileno((temp)()), st.st_mode) < 0)
+ {
+ log<level::DEBUG>("Error setting fchmod for temp file");
+ return -EIO;
+ }
+
+ const EVP_MD* digest = EVP_sha256();
+ size_t hashLen = EVP_MD_block_size(digest);
+ std::vector<uint8_t> hash(hashLen);
+ size_t ivLen = EVP_CIPHER_iv_length(cipher);
+ std::vector<uint8_t> iv(ivLen);
+ std::array<uint8_t, EVP_MAX_KEY_LENGTH> key;
+ size_t keyLen = key.size();
+ std::array<uint8_t, EVP_MAX_MD_SIZE> mac;
+ size_t macLen = mac.size();
+
+ // Create random hash and generate hash key which will be used for
+ // encryption.
+ if (RAND_bytes(hash.data(), hashLen) != 1)
+ {
+ log<level::DEBUG>("Hash genertion failed, bailing out");
+ return -EIO;
+ }
+ if (NULL == HMAC(digest, keyBuff.data(), keyBuff.size(), hash.data(),
+ hashLen, key.data(),
+ reinterpret_cast<unsigned int*>(&keyLen)))
+ {
+ log<level::DEBUG>("Failed to create MAC for authentication");
+ return -EIO;
+ }
+
+ // Generate IV values
+ if (RAND_bytes(iv.data(), ivLen) != 1)
+ {
+ log<level::DEBUG>("UV genertion failed, bailing out");
+ return -EIO;
+ }
+
+ // Encrypt the input data
+ std::vector<uint8_t> outBytes(inBytesLen + EVP_MAX_BLOCK_LENGTH);
+ size_t outBytesLen = 0;
+ if (inBytesLen != 0)
+ {
+ if (encryptDecryptData(true, EVP_aes_128_cbc(), key.data(), keyLen,
+ iv.data(), ivLen, inBytes.data(), inBytesLen,
+ mac.data(), &macLen, outBytes.data(),
+ &outBytesLen) != 0)
+ {
+ log<level::DEBUG>("Error while encrypting the data");
+ return -EIO;
+ }
+ outBytes[outBytesLen] = 0;
+ }
+ OPENSSL_cleanse(key.data(), keyLen);
+
+ // Update the meta password structure.
+ metaPassStruct metaData = {META_PASSWD_SIG, {0, 0}, 0, 0, 0, 0, 0};
+ metaData.hashSize = hashLen;
+ metaData.ivSize = ivLen;
+ metaData.dataSize = bytesWritten;
+ metaData.padSize = outBytesLen - bytesWritten;
+ metaData.macSize = macLen;
+
+ if (fwrite(&metaData, 1, sizeof(metaData), (temp)()) != sizeof(metaData))
+ {
+ log<level::DEBUG>("Error in writing meta data");
+ return -EIO;
+ }
+
+ if (fwrite(&hash[0], 1, hashLen, (temp)()) != hashLen)
+ {
+ log<level::DEBUG>("Error in writing hash data");
+ return -EIO;
+ }
+
+ if (fwrite(&iv[0], 1, ivLen, (temp)()) != ivLen)
+ {
+ log<level::DEBUG>("Error in writing IV data");
+ return -EIO;
+ }
+
+ if (fwrite(&outBytes[0], 1, outBytesLen, (temp)()) != outBytesLen)
+ {
+ log<level::DEBUG>("Error in writing encrypted data");
+ return -EIO;
+ }
+
+ if (fwrite(&mac[0], 1, macLen, (temp)()) != macLen)
+ {
+ log<level::DEBUG>("Error in writing MAC data");
+ return -EIO;
+ }
+
+ if (fflush((temp)()))
+ {
+ log<level::DEBUG>(
+ "File fflush error while writing entries to special file");
+ return -EIO;
+ }
+
+ OPENSSL_cleanse(iv.data(), ivLen);
+
+ // Rename the tmp file to actual file
+ if (std::rename(strTempFileName.data(), passwdFileName) != 0)
+ {
+ log<level::DEBUG>("Failed to rename tmp file to ipmi-pass");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+std::time_t PasswdMgr::getUpdatedFileTime()
+{
struct stat fileStat = {};
if (stat(passwdFileName, &fileStat) != 0)
{
- log<level::DEBUG>("Error in getting last updated time stamp");
- return;
+ log<level::DEBUG>("Error - Getting passwd file time stamp");
+ return -EIO;
}
- fileLastUpdatedTime = fileStat.st_mtime;
- return;
+ return fileStat.st_mtime;
}
} // namespace ipmi
diff --git a/user_channel/passwd_mgr.hpp b/user_channel/passwd_mgr.hpp
index 3078e21..e5625bc 100644
--- a/user_channel/passwd_mgr.hpp
+++ b/user_channel/passwd_mgr.hpp
@@ -18,6 +18,7 @@
#include <ctime>
#include <unordered_map>
+#include <vector>
namespace ipmi
{
@@ -45,6 +46,14 @@ class PasswdMgr
*/
std::string getPasswdByUserName(const std::string& userName);
+ /** @brief Clear username and password entry for the specified user
+ *
+ * @param[in] userName - username
+ *
+ * @return error response
+ */
+ int clearUserEntry(const std::string& userName);
+
private:
using UserName = std::string;
using Password = std::string;
@@ -61,15 +70,32 @@ class PasswdMgr
* authentication.
*/
void initPasswordMap(void);
- /** @brief decrypts the data provided
+
+ /** @brief Function to read the encrypted password file data
+ *
+ * @param[out] outBytes - vector to hold decrypted password file data
*
+ * @return error response
+ */
+ int readPasswdFileData(std::vector<uint8_t>& outBytes);
+ /** @brief Updates special password file by clearing the password entry
+ * for the user specified.
+ *
+ * @param[in] userName - user name entry that has to be removed.
+ *
+ * @return error response
+ */
+ int updatePasswdSpecialFile(const std::string& userName);
+ /** @brief encrypts or decrypt the data provided
+ *
+ * @param[in] doEncrypt - do encrypt if set to true, else do decrypt.
* @param[in] cipher - cipher to be used
* @param[in] key - pointer to the key
* @param[in] keyLen - Length of the key to be used
* @param[in] iv - pointer to initialization vector
* @param[in] ivLen - Length of the iv
* @param[in] inBytes - input data to be encrypted / decrypted
- * @param[in] inBytesLen - input size to be decrypted
+ * @param[in] inBytesLen - input size to be encrypted / decrypted
* @param[in] mac - message authentication code - to figure out corruption
* @param[in] macLen - size of MAC
* @param[in] outBytes - ptr to store output bytes
@@ -77,10 +103,17 @@ class PasswdMgr
*
* @return error response
*/
- int decrypt(const EVP_CIPHER* cipher, uint8_t* key, size_t keyLen,
- uint8_t* iv, size_t ivLen, uint8_t* inBytes, size_t inBytesLen,
- uint8_t* mac, size_t macLen, uint8_t* outBytes,
- size_t* outBytesLen);
+ int encryptDecryptData(bool doEncrypt, const EVP_CIPHER* cipher,
+ uint8_t* key, size_t keyLen, uint8_t* iv,
+ size_t ivLen, uint8_t* inBytes, size_t inBytesLen,
+ uint8_t* mac, size_t* macLen, uint8_t* outBytes,
+ size_t* outBytesLen);
+
+ /** @brief returns updated file time of passwd file entry.
+ *
+ * @return timestamp or -1 for error.
+ */
+ std::time_t getUpdatedFileTime();
};
} // namespace ipmi
diff --git a/user_channel/user_layer.cpp b/user_channel/user_layer.cpp
index dce33d9..ed99137 100644
--- a/user_channel/user_layer.cpp
+++ b/user_channel/user_layer.cpp
@@ -29,4 +29,10 @@ std::string ipmiUserGetPassword(const std::string& userName)
return passwdMgr.getPasswdByUserName(userName);
}
+ipmi_ret_t ipmiUserClearPassword(const std::string& userName)
+{
+ passwdMgr.clearUserEntry(userName);
+ return IPMI_CC_OK;
+}
+
} // namespace ipmi
diff --git a/user_channel/user_layer.hpp b/user_channel/user_layer.hpp
index b797007..4040102 100644
--- a/user_channel/user_layer.hpp
+++ b/user_channel/user_layer.hpp
@@ -28,6 +28,15 @@ namespace ipmi
*/
std::string ipmiUserGetPassword(const std::string& userName);
+/** @brief The IPMI call to clear password entry associated with specified
+ * username
+ *
+ * @param[in] userName
+ *
+ * @return 0 on success, non-zero otherwise.
+ */
+ipmi_ret_t ipmiUserClearPassword(const std::string& userName);
+
// TODO: Define required user layer API Call's which user layer shared library
// must implement.
} // namespace ipmi
OpenPOWER on IntegriCloud