blob: 525b2b72bf3a8a3f507f366915afb136e7c7c8d9 [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);
220 size_t userEPos = 0, lineSize = 0;
221 while (linePtr != NULL)
222 {
223 std::string lineStr(linePtr);
224 if ((userEPos = lineStr.find(":")) != std::string::npos)
225 {
226 lineSize = lineStr.size();
227 passwdMapList.emplace(
228 lineStr.substr(0, userEPos),
229 lineStr.substr(userEPos + 1, lineSize - (userEPos + 1)));
230 }
231 linePtr = strtok_r(NULL, "\n", &nToken);
232 }
233 }
234
235 // Update the timestamp
236 fileLastUpdatedTime = getUpdatedFileTime();
237 return;
238}
239
240int PasswdMgr::readPasswdFileData(std::vector<uint8_t>& outBytes)
241{
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530242 std::array<uint8_t, maxKeySize> keyBuff;
243 std::ifstream keyFile(encryptKeyFileName, std::ios::in | std::ios::binary);
244 if (!keyFile.is_open())
245 {
246 log<level::DEBUG>("Error in opening encryption key file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530247 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530248 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530249 keyFile.read(reinterpret_cast<char*>(keyBuff.data()), keyBuff.size());
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530250 if (keyFile.fail())
251 {
252 log<level::DEBUG>("Error in reading encryption key file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530253 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530254 }
255
256 std::ifstream passwdFile(passwdFileName, std::ios::in | std::ios::binary);
257 if (!passwdFile.is_open())
258 {
259 log<level::DEBUG>("Error in opening ipmi password file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530260 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530261 }
262
263 // calculate file size and read the data
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530264 passwdFile.seekg(0, std::ios::end);
265 ssize_t fileSize = passwdFile.tellg();
266 passwdFile.seekg(0, std::ios::beg);
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530267 std::vector<uint8_t> input(fileSize);
268 passwdFile.read(reinterpret_cast<char*>(input.data()), fileSize);
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530269 if (passwdFile.fail())
270 {
271 log<level::DEBUG>("Error in reading encryption key file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530272 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530273 }
274
275 // verify the signature first
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530276 MetaPassStruct* metaData = reinterpret_cast<MetaPassStruct*>(input.data());
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530277 if (std::strncmp(metaData->signature, META_PASSWD_SIG,
278 sizeof(metaData->signature)))
279 {
280 log<level::DEBUG>("Error signature mismatch in password file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530281 return -EBADMSG;
282 }
283
284 size_t inBytesLen = metaData->dataSize + metaData->padSize;
285 // If data is empty i.e no password map then return success
286 if (inBytesLen == 0)
287 {
288 log<level::DEBUG>("Empty password file");
289 return 0;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530290 }
291
292 // compute the key needed to decrypt
293 std::array<uint8_t, EVP_MAX_KEY_LENGTH> key;
294 auto keyLen = key.size();
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530295 if (NULL == HMAC(EVP_sha256(), keyBuff.data(), keyBuff.size(),
296 input.data() + sizeof(*metaData), metaData->hashSize,
297 key.data(), reinterpret_cast<unsigned int*>(&keyLen)))
298 {
299 log<level::DEBUG>("Failed to create MAC for authentication");
300 return -EIO;
301 }
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530302
303 // decrypt the data
304 uint8_t* iv = input.data() + sizeof(*metaData) + metaData->hashSize;
305 size_t ivLen = metaData->ivSize;
306 uint8_t* inBytes = iv + ivLen;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530307 uint8_t* mac = inBytes + inBytesLen;
308 size_t macLen = metaData->macSize;
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530309
310 size_t outBytesLen = 0;
311 // Resize to actual data size
312 outBytes.resize(inBytesLen + EVP_MAX_BLOCK_LENGTH);
313 if (encryptDecryptData(false, EVP_aes_128_cbc(), key.data(), keyLen, iv,
314 ivLen, inBytes, inBytesLen, mac, &macLen,
315 outBytes.data(), &outBytesLen) != 0)
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530316 {
317 log<level::DEBUG>("Error in decryption");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530318 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530319 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530320 // Resize the vector to outBytesLen
321 outBytes.resize(outBytesLen);
322
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530323 OPENSSL_cleanse(key.data(), keyLen);
324 OPENSSL_cleanse(iv, ivLen);
325
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530326 return 0;
327}
328
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +0530329int PasswdMgr::updatePasswdSpecialFile(const std::string& userName,
330 const std::string& newUserName)
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530331{
332 phosphor::user::shadow::Lock lock();
333
334 size_t bytesWritten = 0;
335 size_t inBytesLen = 0;
336 size_t isUsrFound = false;
337 const EVP_CIPHER* cipher = EVP_aes_128_cbc();
338 std::vector<uint8_t> dataBuf;
339
340 // Read the encrypted file and get the file data
341 // Check user existance and return if not exist.
342 if (readPasswdFileData(dataBuf) != 0)
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530343 {
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530344 log<level::DEBUG>("Error in reading the encrypted pass file");
345 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530346 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530347
348 if (dataBuf.size() != 0)
349 {
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +0530350 inBytesLen =
351 dataBuf.size() + newUserName.size() + EVP_CIPHER_block_size(cipher);
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530352 }
353
354 std::vector<uint8_t> inBytes(inBytesLen);
355 if (inBytesLen != 0)
356 {
357 char* outPtr = reinterpret_cast<char*>(dataBuf.data());
358 size_t userEPos = 0;
359 char* nToken = NULL;
360 char* linePtr = strtok_r(outPtr, "\n", &nToken);
361 while (linePtr != NULL)
362 {
363 std::string lineStr(linePtr);
364 if ((userEPos = lineStr.find(":")) != std::string::npos)
365 {
366 if (userName.compare(lineStr.substr(0, userEPos)) == 0)
367 {
368 isUsrFound = true;
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +0530369 if (!newUserName.empty())
370 {
371 bytesWritten += std::snprintf(
372 reinterpret_cast<char*>(&inBytes[0]) + bytesWritten,
373 (inBytesLen - bytesWritten), "%s%s\n",
374 newUserName.c_str(),
375 lineStr.substr(userEPos, lineStr.size()).data());
376 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530377 }
378 else
379 {
380 bytesWritten += std::snprintf(
381 reinterpret_cast<char*>(&inBytes[0]) + bytesWritten,
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +0530382 (inBytesLen - bytesWritten), "%s\n", lineStr.data());
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530383 }
384 }
385 linePtr = strtok_r(NULL, "\n", &nToken);
386 }
Richard Marian Thomaiyar161f20d2019-01-28 20:33:16 +0530387 inBytesLen = bytesWritten;
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530388 }
389 if (!isUsrFound)
390 {
391 log<level::DEBUG>("User doesn't exist");
392 return 0;
393 }
394
395 // Read the key buff from key file
396 std::array<uint8_t, maxKeySize> keyBuff;
397 std::ifstream keyFile(encryptKeyFileName, std::ios::in | std::ios::binary);
398 if (!keyFile.good())
399 {
400 log<level::DEBUG>("Error in opening encryption key file");
401 return -EIO;
402 }
403 keyFile.read(reinterpret_cast<char*>(keyBuff.data()), keyBuff.size());
404 if (keyFile.fail())
405 {
406 log<level::DEBUG>("Error in reading encryption key file");
407 return -EIO;
408 }
409 keyFile.close();
410
411 // Read the original passwd file mode
412 struct stat st = {};
413 if (stat(passwdFileName, &st) != 0)
414 {
415 log<level::DEBUG>("Error in getting password file fstat()");
416 return -EIO;
417 }
418
419 // Create temporary file for write
420 std::string pwdFile(passwdFileName);
421 std::vector<char> tempFileName(pwdFile.begin(), pwdFile.end());
422 std::vector<char> fileTemplate = {'_', '_', 'X', 'X', 'X',
423 'X', 'X', 'X', '\0'};
424 tempFileName.insert(tempFileName.end(), fileTemplate.begin(),
425 fileTemplate.end());
426 int fd = mkstemp((char*)tempFileName.data());
427 if (fd == -1)
428 {
429 log<level::DEBUG>("Error creating temp file");
430 return -EIO;
431 }
432
433 std::string strTempFileName(tempFileName.data());
434 // Open the temp file for writing from provided fd
435 // By "true", remove it at exit if still there.
436 // This is needed to cleanup the temp file at exception
437 phosphor::user::File temp(fd, strTempFileName, "w", true);
438 if ((temp)() == NULL)
439 {
440 close(fd);
441 log<level::DEBUG>("Error creating temp file");
442 return -EIO;
443 }
444 fd = -1; // don't use fd anymore, as the File object owns it
445
446 // Set the file mode as of actual ipmi-pass file.
447 if (fchmod(fileno((temp)()), st.st_mode) < 0)
448 {
449 log<level::DEBUG>("Error setting fchmod for temp file");
450 return -EIO;
451 }
452
453 const EVP_MD* digest = EVP_sha256();
454 size_t hashLen = EVP_MD_block_size(digest);
455 std::vector<uint8_t> hash(hashLen);
456 size_t ivLen = EVP_CIPHER_iv_length(cipher);
457 std::vector<uint8_t> iv(ivLen);
458 std::array<uint8_t, EVP_MAX_KEY_LENGTH> key;
459 size_t keyLen = key.size();
460 std::array<uint8_t, EVP_MAX_MD_SIZE> mac;
461 size_t macLen = mac.size();
462
463 // Create random hash and generate hash key which will be used for
464 // encryption.
465 if (RAND_bytes(hash.data(), hashLen) != 1)
466 {
467 log<level::DEBUG>("Hash genertion failed, bailing out");
468 return -EIO;
469 }
470 if (NULL == HMAC(digest, keyBuff.data(), keyBuff.size(), hash.data(),
471 hashLen, key.data(),
472 reinterpret_cast<unsigned int*>(&keyLen)))
473 {
474 log<level::DEBUG>("Failed to create MAC for authentication");
475 return -EIO;
476 }
477
478 // Generate IV values
479 if (RAND_bytes(iv.data(), ivLen) != 1)
480 {
481 log<level::DEBUG>("UV genertion failed, bailing out");
482 return -EIO;
483 }
484
485 // Encrypt the input data
486 std::vector<uint8_t> outBytes(inBytesLen + EVP_MAX_BLOCK_LENGTH);
487 size_t outBytesLen = 0;
488 if (inBytesLen != 0)
489 {
490 if (encryptDecryptData(true, EVP_aes_128_cbc(), key.data(), keyLen,
491 iv.data(), ivLen, inBytes.data(), inBytesLen,
492 mac.data(), &macLen, outBytes.data(),
493 &outBytesLen) != 0)
494 {
495 log<level::DEBUG>("Error while encrypting the data");
496 return -EIO;
497 }
498 outBytes[outBytesLen] = 0;
499 }
500 OPENSSL_cleanse(key.data(), keyLen);
501
502 // Update the meta password structure.
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530503 MetaPassStruct metaData = {META_PASSWD_SIG, {0, 0}, 0, 0, 0, 0, 0};
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530504 metaData.hashSize = hashLen;
505 metaData.ivSize = ivLen;
506 metaData.dataSize = bytesWritten;
507 metaData.padSize = outBytesLen - bytesWritten;
508 metaData.macSize = macLen;
509
510 if (fwrite(&metaData, 1, sizeof(metaData), (temp)()) != sizeof(metaData))
511 {
512 log<level::DEBUG>("Error in writing meta data");
513 return -EIO;
514 }
515
516 if (fwrite(&hash[0], 1, hashLen, (temp)()) != hashLen)
517 {
518 log<level::DEBUG>("Error in writing hash data");
519 return -EIO;
520 }
521
522 if (fwrite(&iv[0], 1, ivLen, (temp)()) != ivLen)
523 {
524 log<level::DEBUG>("Error in writing IV data");
525 return -EIO;
526 }
527
528 if (fwrite(&outBytes[0], 1, outBytesLen, (temp)()) != outBytesLen)
529 {
530 log<level::DEBUG>("Error in writing encrypted data");
531 return -EIO;
532 }
533
534 if (fwrite(&mac[0], 1, macLen, (temp)()) != macLen)
535 {
536 log<level::DEBUG>("Error in writing MAC data");
537 return -EIO;
538 }
539
540 if (fflush((temp)()))
541 {
542 log<level::DEBUG>(
543 "File fflush error while writing entries to special file");
544 return -EIO;
545 }
546
547 OPENSSL_cleanse(iv.data(), ivLen);
548
549 // Rename the tmp file to actual file
550 if (std::rename(strTempFileName.data(), passwdFileName) != 0)
551 {
552 log<level::DEBUG>("Failed to rename tmp file to ipmi-pass");
553 return -EIO;
554 }
555
556 return 0;
557}
558
559std::time_t PasswdMgr::getUpdatedFileTime()
560{
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530561 struct stat fileStat = {};
562 if (stat(passwdFileName, &fileStat) != 0)
563 {
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530564 log<level::DEBUG>("Error - Getting passwd file time stamp");
565 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530566 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530567 return fileStat.st_mtime;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530568}
569
570} // namespace ipmi