blob: 66bdef0d83ac97fc1141f10168c02cd144c67649 [file] [log] [blame]
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +05301/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
17#include "passwd_mgr.hpp"
18
AppaRao Pulib29b5ab2018-05-17 10:28:48 +053019#include "file.hpp"
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +053020#include "shadowlock.hpp"
21
22#include <openssl/hmac.h>
AppaRao Pulib29b5ab2018-05-17 10:28:48 +053023#include <openssl/rand.h>
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +053024#include <openssl/sha.h>
25#include <string.h>
26#include <sys/stat.h>
AppaRao Pulib29b5ab2018-05-17 10:28:48 +053027#include <unistd.h>
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +053028
AppaRao Pulib29b5ab2018-05-17 10:28:48 +053029#include <cerrno>
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +053030#include <cstring>
31#include <fstream>
AppaRao Pulib29b5ab2018-05-17 10:28:48 +053032#include <iomanip>
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +053033#include <phosphor-logging/log.hpp>
34
35namespace ipmi
36{
37
38static const char* passwdFileName = "/etc/ipmi_pass";
39static const char* encryptKeyFileName = "/etc/key_file";
40static const size_t maxKeySize = 8;
41
AppaRao Pulib29b5ab2018-05-17 10:28:48 +053042#define META_PASSWD_SIG "=OPENBMC="
43
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +053044/*
45 * Meta data struct for encrypted password file
46 */
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +053047struct MetaPassStruct
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +053048{
49 char signature[10];
50 unsigned char reseved[2];
51 size_t hashSize;
52 size_t ivSize;
53 size_t dataSize;
54 size_t padSize;
55 size_t macSize;
56};
57
58using namespace phosphor::logging;
59
60PasswdMgr::PasswdMgr()
61{
62 initPasswordMap();
63}
64
65std::string PasswdMgr::getPasswdByUserName(const std::string& userName)
66{
67 checkAndReload();
68 auto iter = passwdMapList.find(userName);
69 if (iter == passwdMapList.end())
70 {
71 return std::string();
72 }
73 return iter->second;
74}
75
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +053076int PasswdMgr::updateUserEntry(const std::string& userName,
77 const std::string& newUserName)
AppaRao Pulib29b5ab2018-05-17 10:28:48 +053078{
79 std::time_t updatedTime = getUpdatedFileTime();
80 // Check file time stamp to know passwdMapList is up-to-date.
81 // If not up-to-date, then updatePasswdSpecialFile will read and
82 // check the user entry existance.
83 if (fileLastUpdatedTime == updatedTime && updatedTime != -EIO)
84 {
85 if (passwdMapList.find(userName) == passwdMapList.end())
86 {
87 log<level::DEBUG>("User not found");
88 return 0;
89 }
90 }
91
92 // Write passwdMap to Encryted file
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +053093 if (updatePasswdSpecialFile(userName, newUserName) != 0)
AppaRao Pulib29b5ab2018-05-17 10:28:48 +053094 {
95 log<level::DEBUG>("Passwd file update failed");
96 return -EIO;
97 }
98
99 log<level::DEBUG>("Passwd file updated successfully");
100 return 0;
101}
102
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530103void PasswdMgr::checkAndReload(void)
104{
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530105 std::time_t updatedTime = getUpdatedFileTime();
106 if (fileLastUpdatedTime != updatedTime && updatedTime != -1)
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530107 {
108 log<level::DEBUG>("Reloading password map list");
109 passwdMapList.clear();
110 initPasswordMap();
111 }
112}
113
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530114int PasswdMgr::encryptDecryptData(bool doEncrypt, const EVP_CIPHER* cipher,
115 uint8_t* key, size_t keyLen, uint8_t* iv,
116 size_t ivLen, uint8_t* inBytes,
117 size_t inBytesLen, uint8_t* mac,
118 size_t* macLen, unsigned char* outBytes,
119 size_t* outBytesLen)
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530120{
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530121 if (cipher == NULL || key == NULL || iv == NULL || inBytes == NULL ||
122 outBytes == NULL || mac == NULL || inBytesLen == 0 ||
123 (size_t)EVP_CIPHER_key_length(cipher) > keyLen ||
124 (size_t)EVP_CIPHER_iv_length(cipher) > ivLen)
125 {
126 log<level::DEBUG>("Error Invalid Inputs");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530127 return -EINVAL;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530128 }
129
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530130 if (!doEncrypt)
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530131 {
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530132 // verify MAC before decrypting the data.
133 std::array<uint8_t, EVP_MAX_MD_SIZE> calMac;
134 size_t calMacLen = calMac.size();
135 // calculate MAC for the encrypted message.
136 if (NULL == HMAC(EVP_sha256(), key, keyLen, inBytes, inBytesLen,
137 calMac.data(),
138 reinterpret_cast<unsigned int*>(&calMacLen)))
139 {
140 log<level::DEBUG>("Error: Failed to calculate MAC");
141 return -EIO;
142 }
143 if (!((calMacLen == *macLen) &&
144 (std::memcmp(calMac.data(), mac, calMacLen) == 0)))
145 {
146 log<level::DEBUG>("Authenticated message doesn't match");
147 return -EBADMSG;
148 }
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530149 }
150
151 std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)> ctx(
152 EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);
153 EVP_CIPHER_CTX_set_padding(ctx.get(), 1);
154
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530155 // Set key & IV
156 int retval = EVP_CipherInit_ex(ctx.get(), cipher, NULL, key, iv,
157 static_cast<int>(doEncrypt));
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530158 if (!retval)
159 {
160 log<level::DEBUG>("EVP_CipherInit_ex failed",
161 entry("RET_VAL=%d", retval));
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530162 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530163 }
164
165 int outLen = 0, outEVPLen = 0;
166 if ((retval = EVP_CipherUpdate(ctx.get(), outBytes + outLen, &outEVPLen,
167 inBytes, inBytesLen)))
168 {
169 outLen += outEVPLen;
170 if ((retval =
171 EVP_CipherFinal(ctx.get(), outBytes + outLen, &outEVPLen)))
172 {
173 outLen += outEVPLen;
174 *outBytesLen = outLen;
175 }
176 else
177 {
178 log<level::DEBUG>("EVP_CipherFinal fails",
179 entry("RET_VAL=%d", retval));
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530180 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530181 }
182 }
183 else
184 {
185 log<level::DEBUG>("EVP_CipherUpdate fails",
186 entry("RET_VAL=%d", retval));
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530187 return -EIO;
188 }
189
190 if (doEncrypt)
191 {
192 // Create MAC for the encrypted message
193 if (NULL == HMAC(EVP_sha256(), key, keyLen, outBytes, *outBytesLen, mac,
194 reinterpret_cast<unsigned int*>(macLen)))
195 {
196 log<level::DEBUG>("Failed to create authentication");
197 return -EIO;
198 }
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530199 }
200 return 0;
201}
202
203void PasswdMgr::initPasswordMap(void)
204{
205 phosphor::user::shadow::Lock lock();
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530206 std::vector<uint8_t> dataBuf;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530207
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530208 if (readPasswdFileData(dataBuf) != 0)
209 {
210 log<level::DEBUG>("Error in reading the encrypted pass file");
211 return;
212 }
213
214 if (dataBuf.size() != 0)
215 {
216 // populate the user list with password
217 char* outPtr = reinterpret_cast<char*>(dataBuf.data());
218 char* nToken = NULL;
219 char* linePtr = strtok_r(outPtr, "\n", &nToken);
Patrick Venture51d0c402019-08-19 11:19:19 -0700220 size_t lineSize = 0;
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530221 while (linePtr != NULL)
222 {
Patrick Venture51d0c402019-08-19 11:19:19 -0700223 size_t userEPos = 0;
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530224 std::string lineStr(linePtr);
225 if ((userEPos = lineStr.find(":")) != std::string::npos)
226 {
227 lineSize = lineStr.size();
228 passwdMapList.emplace(
229 lineStr.substr(0, userEPos),
230 lineStr.substr(userEPos + 1, lineSize - (userEPos + 1)));
231 }
232 linePtr = strtok_r(NULL, "\n", &nToken);
233 }
234 }
235
236 // Update the timestamp
237 fileLastUpdatedTime = getUpdatedFileTime();
238 return;
239}
240
241int PasswdMgr::readPasswdFileData(std::vector<uint8_t>& outBytes)
242{
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530243 std::array<uint8_t, maxKeySize> keyBuff;
244 std::ifstream keyFile(encryptKeyFileName, std::ios::in | std::ios::binary);
245 if (!keyFile.is_open())
246 {
247 log<level::DEBUG>("Error in opening encryption key file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530248 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530249 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530250 keyFile.read(reinterpret_cast<char*>(keyBuff.data()), keyBuff.size());
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530251 if (keyFile.fail())
252 {
253 log<level::DEBUG>("Error in reading encryption key file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530254 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530255 }
256
257 std::ifstream passwdFile(passwdFileName, std::ios::in | std::ios::binary);
258 if (!passwdFile.is_open())
259 {
260 log<level::DEBUG>("Error in opening ipmi password file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530261 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530262 }
263
264 // calculate file size and read the data
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530265 passwdFile.seekg(0, std::ios::end);
266 ssize_t fileSize = passwdFile.tellg();
267 passwdFile.seekg(0, std::ios::beg);
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530268 std::vector<uint8_t> input(fileSize);
269 passwdFile.read(reinterpret_cast<char*>(input.data()), fileSize);
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530270 if (passwdFile.fail())
271 {
272 log<level::DEBUG>("Error in reading encryption key file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530273 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530274 }
275
276 // verify the signature first
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530277 MetaPassStruct* metaData = reinterpret_cast<MetaPassStruct*>(input.data());
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530278 if (std::strncmp(metaData->signature, META_PASSWD_SIG,
279 sizeof(metaData->signature)))
280 {
281 log<level::DEBUG>("Error signature mismatch in password file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530282 return -EBADMSG;
283 }
284
285 size_t inBytesLen = metaData->dataSize + metaData->padSize;
286 // If data is empty i.e no password map then return success
287 if (inBytesLen == 0)
288 {
289 log<level::DEBUG>("Empty password file");
290 return 0;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530291 }
292
293 // compute the key needed to decrypt
294 std::array<uint8_t, EVP_MAX_KEY_LENGTH> key;
295 auto keyLen = key.size();
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530296 if (NULL == HMAC(EVP_sha256(), keyBuff.data(), keyBuff.size(),
297 input.data() + sizeof(*metaData), metaData->hashSize,
298 key.data(), reinterpret_cast<unsigned int*>(&keyLen)))
299 {
300 log<level::DEBUG>("Failed to create MAC for authentication");
301 return -EIO;
302 }
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530303
304 // decrypt the data
305 uint8_t* iv = input.data() + sizeof(*metaData) + metaData->hashSize;
306 size_t ivLen = metaData->ivSize;
307 uint8_t* inBytes = iv + ivLen;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530308 uint8_t* mac = inBytes + inBytesLen;
309 size_t macLen = metaData->macSize;
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530310
311 size_t outBytesLen = 0;
312 // Resize to actual data size
313 outBytes.resize(inBytesLen + EVP_MAX_BLOCK_LENGTH);
314 if (encryptDecryptData(false, EVP_aes_128_cbc(), key.data(), keyLen, iv,
315 ivLen, inBytes, inBytesLen, mac, &macLen,
316 outBytes.data(), &outBytesLen) != 0)
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530317 {
318 log<level::DEBUG>("Error in decryption");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530319 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530320 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530321 // Resize the vector to outBytesLen
322 outBytes.resize(outBytesLen);
323
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530324 OPENSSL_cleanse(key.data(), keyLen);
325 OPENSSL_cleanse(iv, ivLen);
326
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530327 return 0;
328}
329
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +0530330int PasswdMgr::updatePasswdSpecialFile(const std::string& userName,
331 const std::string& newUserName)
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530332{
333 phosphor::user::shadow::Lock lock();
334
335 size_t bytesWritten = 0;
336 size_t inBytesLen = 0;
337 size_t isUsrFound = false;
338 const EVP_CIPHER* cipher = EVP_aes_128_cbc();
339 std::vector<uint8_t> dataBuf;
340
341 // Read the encrypted file and get the file data
342 // Check user existance and return if not exist.
343 if (readPasswdFileData(dataBuf) != 0)
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530344 {
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530345 log<level::DEBUG>("Error in reading the encrypted pass file");
346 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530347 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530348
349 if (dataBuf.size() != 0)
350 {
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +0530351 inBytesLen =
352 dataBuf.size() + newUserName.size() + EVP_CIPHER_block_size(cipher);
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530353 }
354
355 std::vector<uint8_t> inBytes(inBytesLen);
356 if (inBytesLen != 0)
357 {
358 char* outPtr = reinterpret_cast<char*>(dataBuf.data());
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530359 char* nToken = NULL;
360 char* linePtr = strtok_r(outPtr, "\n", &nToken);
361 while (linePtr != NULL)
362 {
Patrick Venture51d0c402019-08-19 11:19:19 -0700363 size_t userEPos = 0;
364
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530365 std::string lineStr(linePtr);
366 if ((userEPos = lineStr.find(":")) != std::string::npos)
367 {
368 if (userName.compare(lineStr.substr(0, userEPos)) == 0)
369 {
370 isUsrFound = true;
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +0530371 if (!newUserName.empty())
372 {
373 bytesWritten += std::snprintf(
374 reinterpret_cast<char*>(&inBytes[0]) + bytesWritten,
375 (inBytesLen - bytesWritten), "%s%s\n",
376 newUserName.c_str(),
377 lineStr.substr(userEPos, lineStr.size()).data());
378 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530379 }
380 else
381 {
382 bytesWritten += std::snprintf(
383 reinterpret_cast<char*>(&inBytes[0]) + bytesWritten,
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +0530384 (inBytesLen - bytesWritten), "%s\n", lineStr.data());
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530385 }
386 }
387 linePtr = strtok_r(NULL, "\n", &nToken);
388 }
Richard Marian Thomaiyar161f20d2019-01-28 20:33:16 +0530389 inBytesLen = bytesWritten;
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530390 }
391 if (!isUsrFound)
392 {
393 log<level::DEBUG>("User doesn't exist");
394 return 0;
395 }
396
397 // Read the key buff from key file
398 std::array<uint8_t, maxKeySize> keyBuff;
399 std::ifstream keyFile(encryptKeyFileName, std::ios::in | std::ios::binary);
400 if (!keyFile.good())
401 {
402 log<level::DEBUG>("Error in opening encryption key file");
403 return -EIO;
404 }
405 keyFile.read(reinterpret_cast<char*>(keyBuff.data()), keyBuff.size());
406 if (keyFile.fail())
407 {
408 log<level::DEBUG>("Error in reading encryption key file");
409 return -EIO;
410 }
411 keyFile.close();
412
413 // Read the original passwd file mode
414 struct stat st = {};
415 if (stat(passwdFileName, &st) != 0)
416 {
417 log<level::DEBUG>("Error in getting password file fstat()");
418 return -EIO;
419 }
420
421 // Create temporary file for write
422 std::string pwdFile(passwdFileName);
423 std::vector<char> tempFileName(pwdFile.begin(), pwdFile.end());
424 std::vector<char> fileTemplate = {'_', '_', 'X', 'X', 'X',
425 'X', 'X', 'X', '\0'};
426 tempFileName.insert(tempFileName.end(), fileTemplate.begin(),
427 fileTemplate.end());
428 int fd = mkstemp((char*)tempFileName.data());
429 if (fd == -1)
430 {
431 log<level::DEBUG>("Error creating temp file");
432 return -EIO;
433 }
434
435 std::string strTempFileName(tempFileName.data());
436 // Open the temp file for writing from provided fd
437 // By "true", remove it at exit if still there.
438 // This is needed to cleanup the temp file at exception
439 phosphor::user::File temp(fd, strTempFileName, "w", true);
440 if ((temp)() == NULL)
441 {
442 close(fd);
443 log<level::DEBUG>("Error creating temp file");
444 return -EIO;
445 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530446
447 // Set the file mode as of actual ipmi-pass file.
448 if (fchmod(fileno((temp)()), st.st_mode) < 0)
449 {
450 log<level::DEBUG>("Error setting fchmod for temp file");
451 return -EIO;
452 }
453
454 const EVP_MD* digest = EVP_sha256();
455 size_t hashLen = EVP_MD_block_size(digest);
456 std::vector<uint8_t> hash(hashLen);
457 size_t ivLen = EVP_CIPHER_iv_length(cipher);
458 std::vector<uint8_t> iv(ivLen);
459 std::array<uint8_t, EVP_MAX_KEY_LENGTH> key;
460 size_t keyLen = key.size();
461 std::array<uint8_t, EVP_MAX_MD_SIZE> mac;
462 size_t macLen = mac.size();
463
464 // Create random hash and generate hash key which will be used for
465 // encryption.
466 if (RAND_bytes(hash.data(), hashLen) != 1)
467 {
468 log<level::DEBUG>("Hash genertion failed, bailing out");
469 return -EIO;
470 }
471 if (NULL == HMAC(digest, keyBuff.data(), keyBuff.size(), hash.data(),
472 hashLen, key.data(),
473 reinterpret_cast<unsigned int*>(&keyLen)))
474 {
475 log<level::DEBUG>("Failed to create MAC for authentication");
476 return -EIO;
477 }
478
479 // Generate IV values
480 if (RAND_bytes(iv.data(), ivLen) != 1)
481 {
482 log<level::DEBUG>("UV genertion failed, bailing out");
483 return -EIO;
484 }
485
486 // Encrypt the input data
487 std::vector<uint8_t> outBytes(inBytesLen + EVP_MAX_BLOCK_LENGTH);
488 size_t outBytesLen = 0;
489 if (inBytesLen != 0)
490 {
491 if (encryptDecryptData(true, EVP_aes_128_cbc(), key.data(), keyLen,
492 iv.data(), ivLen, inBytes.data(), inBytesLen,
493 mac.data(), &macLen, outBytes.data(),
494 &outBytesLen) != 0)
495 {
496 log<level::DEBUG>("Error while encrypting the data");
497 return -EIO;
498 }
499 outBytes[outBytesLen] = 0;
500 }
501 OPENSSL_cleanse(key.data(), keyLen);
502
503 // Update the meta password structure.
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530504 MetaPassStruct metaData = {META_PASSWD_SIG, {0, 0}, 0, 0, 0, 0, 0};
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530505 metaData.hashSize = hashLen;
506 metaData.ivSize = ivLen;
507 metaData.dataSize = bytesWritten;
508 metaData.padSize = outBytesLen - bytesWritten;
509 metaData.macSize = macLen;
510
511 if (fwrite(&metaData, 1, sizeof(metaData), (temp)()) != sizeof(metaData))
512 {
513 log<level::DEBUG>("Error in writing meta data");
514 return -EIO;
515 }
516
517 if (fwrite(&hash[0], 1, hashLen, (temp)()) != hashLen)
518 {
519 log<level::DEBUG>("Error in writing hash data");
520 return -EIO;
521 }
522
523 if (fwrite(&iv[0], 1, ivLen, (temp)()) != ivLen)
524 {
525 log<level::DEBUG>("Error in writing IV data");
526 return -EIO;
527 }
528
529 if (fwrite(&outBytes[0], 1, outBytesLen, (temp)()) != outBytesLen)
530 {
531 log<level::DEBUG>("Error in writing encrypted data");
532 return -EIO;
533 }
534
535 if (fwrite(&mac[0], 1, macLen, (temp)()) != macLen)
536 {
537 log<level::DEBUG>("Error in writing MAC data");
538 return -EIO;
539 }
540
541 if (fflush((temp)()))
542 {
543 log<level::DEBUG>(
544 "File fflush error while writing entries to special file");
545 return -EIO;
546 }
547
548 OPENSSL_cleanse(iv.data(), ivLen);
549
550 // Rename the tmp file to actual file
551 if (std::rename(strTempFileName.data(), passwdFileName) != 0)
552 {
553 log<level::DEBUG>("Failed to rename tmp file to ipmi-pass");
554 return -EIO;
555 }
556
557 return 0;
558}
559
560std::time_t PasswdMgr::getUpdatedFileTime()
561{
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530562 struct stat fileStat = {};
563 if (stat(passwdFileName, &fileStat) != 0)
564 {
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530565 log<level::DEBUG>("Error - Getting passwd file time stamp");
566 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530567 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530568 return fileStat.st_mtime;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530569}
570
571} // namespace ipmi