blob: d4ff39fab4fb28448b67f24f2e654142069292a2 [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
44static inline size_t blockRound(size_t odd, size_t blk)
45{
46 return ((odd) + (((blk) - ((odd) & ((blk)-1))) & ((blk)-1)));
47}
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +053048
49/*
50 * Meta data struct for encrypted password file
51 */
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +053052struct MetaPassStruct
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +053053{
54 char signature[10];
55 unsigned char reseved[2];
56 size_t hashSize;
57 size_t ivSize;
58 size_t dataSize;
59 size_t padSize;
60 size_t macSize;
61};
62
63using namespace phosphor::logging;
64
65PasswdMgr::PasswdMgr()
66{
67 initPasswordMap();
68}
69
70std::string PasswdMgr::getPasswdByUserName(const std::string& userName)
71{
72 checkAndReload();
73 auto iter = passwdMapList.find(userName);
74 if (iter == passwdMapList.end())
75 {
76 return std::string();
77 }
78 return iter->second;
79}
80
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +053081int PasswdMgr::updateUserEntry(const std::string& userName,
82 const std::string& newUserName)
AppaRao Pulib29b5ab2018-05-17 10:28:48 +053083{
84 std::time_t updatedTime = getUpdatedFileTime();
85 // Check file time stamp to know passwdMapList is up-to-date.
86 // If not up-to-date, then updatePasswdSpecialFile will read and
87 // check the user entry existance.
88 if (fileLastUpdatedTime == updatedTime && updatedTime != -EIO)
89 {
90 if (passwdMapList.find(userName) == passwdMapList.end())
91 {
92 log<level::DEBUG>("User not found");
93 return 0;
94 }
95 }
96
97 // Write passwdMap to Encryted file
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +053098 if (updatePasswdSpecialFile(userName, newUserName) != 0)
AppaRao Pulib29b5ab2018-05-17 10:28:48 +053099 {
100 log<level::DEBUG>("Passwd file update failed");
101 return -EIO;
102 }
103
104 log<level::DEBUG>("Passwd file updated successfully");
105 return 0;
106}
107
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530108void PasswdMgr::checkAndReload(void)
109{
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530110 std::time_t updatedTime = getUpdatedFileTime();
111 if (fileLastUpdatedTime != updatedTime && updatedTime != -1)
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530112 {
113 log<level::DEBUG>("Reloading password map list");
114 passwdMapList.clear();
115 initPasswordMap();
116 }
117}
118
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530119int PasswdMgr::encryptDecryptData(bool doEncrypt, const EVP_CIPHER* cipher,
120 uint8_t* key, size_t keyLen, uint8_t* iv,
121 size_t ivLen, uint8_t* inBytes,
122 size_t inBytesLen, uint8_t* mac,
123 size_t* macLen, unsigned char* outBytes,
124 size_t* outBytesLen)
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530125{
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530126 if (cipher == NULL || key == NULL || iv == NULL || inBytes == NULL ||
127 outBytes == NULL || mac == NULL || inBytesLen == 0 ||
128 (size_t)EVP_CIPHER_key_length(cipher) > keyLen ||
129 (size_t)EVP_CIPHER_iv_length(cipher) > ivLen)
130 {
131 log<level::DEBUG>("Error Invalid Inputs");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530132 return -EINVAL;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530133 }
134
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530135 if (!doEncrypt)
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530136 {
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530137 // verify MAC before decrypting the data.
138 std::array<uint8_t, EVP_MAX_MD_SIZE> calMac;
139 size_t calMacLen = calMac.size();
140 // calculate MAC for the encrypted message.
141 if (NULL == HMAC(EVP_sha256(), key, keyLen, inBytes, inBytesLen,
142 calMac.data(),
143 reinterpret_cast<unsigned int*>(&calMacLen)))
144 {
145 log<level::DEBUG>("Error: Failed to calculate MAC");
146 return -EIO;
147 }
148 if (!((calMacLen == *macLen) &&
149 (std::memcmp(calMac.data(), mac, calMacLen) == 0)))
150 {
151 log<level::DEBUG>("Authenticated message doesn't match");
152 return -EBADMSG;
153 }
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530154 }
155
156 std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)> ctx(
157 EVP_CIPHER_CTX_new(), ::EVP_CIPHER_CTX_free);
158 EVP_CIPHER_CTX_set_padding(ctx.get(), 1);
159
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530160 // Set key & IV
161 int retval = EVP_CipherInit_ex(ctx.get(), cipher, NULL, key, iv,
162 static_cast<int>(doEncrypt));
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530163 if (!retval)
164 {
165 log<level::DEBUG>("EVP_CipherInit_ex failed",
166 entry("RET_VAL=%d", retval));
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530167 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530168 }
169
170 int outLen = 0, outEVPLen = 0;
171 if ((retval = EVP_CipherUpdate(ctx.get(), outBytes + outLen, &outEVPLen,
172 inBytes, inBytesLen)))
173 {
174 outLen += outEVPLen;
175 if ((retval =
176 EVP_CipherFinal(ctx.get(), outBytes + outLen, &outEVPLen)))
177 {
178 outLen += outEVPLen;
179 *outBytesLen = outLen;
180 }
181 else
182 {
183 log<level::DEBUG>("EVP_CipherFinal fails",
184 entry("RET_VAL=%d", retval));
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530185 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530186 }
187 }
188 else
189 {
190 log<level::DEBUG>("EVP_CipherUpdate fails",
191 entry("RET_VAL=%d", retval));
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530192 return -EIO;
193 }
194
195 if (doEncrypt)
196 {
197 // Create MAC for the encrypted message
198 if (NULL == HMAC(EVP_sha256(), key, keyLen, outBytes, *outBytesLen, mac,
199 reinterpret_cast<unsigned int*>(macLen)))
200 {
201 log<level::DEBUG>("Failed to create authentication");
202 return -EIO;
203 }
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530204 }
205 return 0;
206}
207
208void PasswdMgr::initPasswordMap(void)
209{
210 phosphor::user::shadow::Lock lock();
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530211 std::vector<uint8_t> dataBuf;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530212
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530213 if (readPasswdFileData(dataBuf) != 0)
214 {
215 log<level::DEBUG>("Error in reading the encrypted pass file");
216 return;
217 }
218
219 if (dataBuf.size() != 0)
220 {
221 // populate the user list with password
222 char* outPtr = reinterpret_cast<char*>(dataBuf.data());
223 char* nToken = NULL;
224 char* linePtr = strtok_r(outPtr, "\n", &nToken);
225 size_t userEPos = 0, lineSize = 0;
226 while (linePtr != NULL)
227 {
228 std::string lineStr(linePtr);
229 if ((userEPos = lineStr.find(":")) != std::string::npos)
230 {
231 lineSize = lineStr.size();
232 passwdMapList.emplace(
233 lineStr.substr(0, userEPos),
234 lineStr.substr(userEPos + 1, lineSize - (userEPos + 1)));
235 }
236 linePtr = strtok_r(NULL, "\n", &nToken);
237 }
238 }
239
240 // Update the timestamp
241 fileLastUpdatedTime = getUpdatedFileTime();
242 return;
243}
244
245int PasswdMgr::readPasswdFileData(std::vector<uint8_t>& outBytes)
246{
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530247 std::array<uint8_t, maxKeySize> keyBuff;
248 std::ifstream keyFile(encryptKeyFileName, std::ios::in | std::ios::binary);
249 if (!keyFile.is_open())
250 {
251 log<level::DEBUG>("Error in opening encryption key file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530252 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530253 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530254 keyFile.read(reinterpret_cast<char*>(keyBuff.data()), keyBuff.size());
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530255 if (keyFile.fail())
256 {
257 log<level::DEBUG>("Error in reading encryption key file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530258 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530259 }
260
261 std::ifstream passwdFile(passwdFileName, std::ios::in | std::ios::binary);
262 if (!passwdFile.is_open())
263 {
264 log<level::DEBUG>("Error in opening ipmi password file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530265 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530266 }
267
268 // calculate file size and read the data
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530269 passwdFile.seekg(0, std::ios::end);
270 ssize_t fileSize = passwdFile.tellg();
271 passwdFile.seekg(0, std::ios::beg);
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530272 std::vector<uint8_t> input(fileSize);
273 passwdFile.read(reinterpret_cast<char*>(input.data()), fileSize);
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530274 if (passwdFile.fail())
275 {
276 log<level::DEBUG>("Error in reading encryption key file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530277 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530278 }
279
280 // verify the signature first
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530281 MetaPassStruct* metaData = reinterpret_cast<MetaPassStruct*>(input.data());
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530282 if (std::strncmp(metaData->signature, META_PASSWD_SIG,
283 sizeof(metaData->signature)))
284 {
285 log<level::DEBUG>("Error signature mismatch in password file");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530286 return -EBADMSG;
287 }
288
289 size_t inBytesLen = metaData->dataSize + metaData->padSize;
290 // If data is empty i.e no password map then return success
291 if (inBytesLen == 0)
292 {
293 log<level::DEBUG>("Empty password file");
294 return 0;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530295 }
296
297 // compute the key needed to decrypt
298 std::array<uint8_t, EVP_MAX_KEY_LENGTH> key;
299 auto keyLen = key.size();
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530300 if (NULL == HMAC(EVP_sha256(), keyBuff.data(), keyBuff.size(),
301 input.data() + sizeof(*metaData), metaData->hashSize,
302 key.data(), reinterpret_cast<unsigned int*>(&keyLen)))
303 {
304 log<level::DEBUG>("Failed to create MAC for authentication");
305 return -EIO;
306 }
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530307
308 // decrypt the data
309 uint8_t* iv = input.data() + sizeof(*metaData) + metaData->hashSize;
310 size_t ivLen = metaData->ivSize;
311 uint8_t* inBytes = iv + ivLen;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530312 uint8_t* mac = inBytes + inBytesLen;
313 size_t macLen = metaData->macSize;
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530314
315 size_t outBytesLen = 0;
316 // Resize to actual data size
317 outBytes.resize(inBytesLen + EVP_MAX_BLOCK_LENGTH);
318 if (encryptDecryptData(false, EVP_aes_128_cbc(), key.data(), keyLen, iv,
319 ivLen, inBytes, inBytesLen, mac, &macLen,
320 outBytes.data(), &outBytesLen) != 0)
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530321 {
322 log<level::DEBUG>("Error in decryption");
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530323 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530324 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530325 // Resize the vector to outBytesLen
326 outBytes.resize(outBytesLen);
327
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530328 OPENSSL_cleanse(key.data(), keyLen);
329 OPENSSL_cleanse(iv, ivLen);
330
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530331 return 0;
332}
333
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +0530334int PasswdMgr::updatePasswdSpecialFile(const std::string& userName,
335 const std::string& newUserName)
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530336{
337 phosphor::user::shadow::Lock lock();
338
339 size_t bytesWritten = 0;
340 size_t inBytesLen = 0;
341 size_t isUsrFound = false;
342 const EVP_CIPHER* cipher = EVP_aes_128_cbc();
343 std::vector<uint8_t> dataBuf;
344
345 // Read the encrypted file and get the file data
346 // Check user existance and return if not exist.
347 if (readPasswdFileData(dataBuf) != 0)
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530348 {
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530349 log<level::DEBUG>("Error in reading the encrypted pass file");
350 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530351 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530352
353 if (dataBuf.size() != 0)
354 {
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +0530355 inBytesLen =
356 dataBuf.size() + newUserName.size() + EVP_CIPHER_block_size(cipher);
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530357 }
358
359 std::vector<uint8_t> inBytes(inBytesLen);
360 if (inBytesLen != 0)
361 {
362 char* outPtr = reinterpret_cast<char*>(dataBuf.data());
363 size_t userEPos = 0;
364 char* nToken = NULL;
365 char* linePtr = strtok_r(outPtr, "\n", &nToken);
366 while (linePtr != NULL)
367 {
368 std::string lineStr(linePtr);
369 if ((userEPos = lineStr.find(":")) != std::string::npos)
370 {
371 if (userName.compare(lineStr.substr(0, userEPos)) == 0)
372 {
373 isUsrFound = true;
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +0530374 if (!newUserName.empty())
375 {
376 bytesWritten += std::snprintf(
377 reinterpret_cast<char*>(&inBytes[0]) + bytesWritten,
378 (inBytesLen - bytesWritten), "%s%s\n",
379 newUserName.c_str(),
380 lineStr.substr(userEPos, lineStr.size()).data());
381 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530382 }
383 else
384 {
385 bytesWritten += std::snprintf(
386 reinterpret_cast<char*>(&inBytes[0]) + bytesWritten,
Richard Marian Thomaiyar42bed642018-09-21 12:28:57 +0530387 (inBytesLen - bytesWritten), "%s\n", lineStr.data());
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530388 }
389 }
390 linePtr = strtok_r(NULL, "\n", &nToken);
391 }
392
393 // Round of to block size and padding remaing bytes with zero.
394 inBytesLen = blockRound(bytesWritten, EVP_CIPHER_block_size(cipher));
395 std::memset(&inBytes[0] + bytesWritten, 0, inBytesLen - bytesWritten);
396 }
397 if (!isUsrFound)
398 {
399 log<level::DEBUG>("User doesn't exist");
400 return 0;
401 }
402
403 // Read the key buff from key file
404 std::array<uint8_t, maxKeySize> keyBuff;
405 std::ifstream keyFile(encryptKeyFileName, std::ios::in | std::ios::binary);
406 if (!keyFile.good())
407 {
408 log<level::DEBUG>("Error in opening encryption key file");
409 return -EIO;
410 }
411 keyFile.read(reinterpret_cast<char*>(keyBuff.data()), keyBuff.size());
412 if (keyFile.fail())
413 {
414 log<level::DEBUG>("Error in reading encryption key file");
415 return -EIO;
416 }
417 keyFile.close();
418
419 // Read the original passwd file mode
420 struct stat st = {};
421 if (stat(passwdFileName, &st) != 0)
422 {
423 log<level::DEBUG>("Error in getting password file fstat()");
424 return -EIO;
425 }
426
427 // Create temporary file for write
428 std::string pwdFile(passwdFileName);
429 std::vector<char> tempFileName(pwdFile.begin(), pwdFile.end());
430 std::vector<char> fileTemplate = {'_', '_', 'X', 'X', 'X',
431 'X', 'X', 'X', '\0'};
432 tempFileName.insert(tempFileName.end(), fileTemplate.begin(),
433 fileTemplate.end());
434 int fd = mkstemp((char*)tempFileName.data());
435 if (fd == -1)
436 {
437 log<level::DEBUG>("Error creating temp file");
438 return -EIO;
439 }
440
441 std::string strTempFileName(tempFileName.data());
442 // Open the temp file for writing from provided fd
443 // By "true", remove it at exit if still there.
444 // This is needed to cleanup the temp file at exception
445 phosphor::user::File temp(fd, strTempFileName, "w", true);
446 if ((temp)() == NULL)
447 {
448 close(fd);
449 log<level::DEBUG>("Error creating temp file");
450 return -EIO;
451 }
452 fd = -1; // don't use fd anymore, as the File object owns it
453
454 // Set the file mode as of actual ipmi-pass file.
455 if (fchmod(fileno((temp)()), st.st_mode) < 0)
456 {
457 log<level::DEBUG>("Error setting fchmod for temp file");
458 return -EIO;
459 }
460
461 const EVP_MD* digest = EVP_sha256();
462 size_t hashLen = EVP_MD_block_size(digest);
463 std::vector<uint8_t> hash(hashLen);
464 size_t ivLen = EVP_CIPHER_iv_length(cipher);
465 std::vector<uint8_t> iv(ivLen);
466 std::array<uint8_t, EVP_MAX_KEY_LENGTH> key;
467 size_t keyLen = key.size();
468 std::array<uint8_t, EVP_MAX_MD_SIZE> mac;
469 size_t macLen = mac.size();
470
471 // Create random hash and generate hash key which will be used for
472 // encryption.
473 if (RAND_bytes(hash.data(), hashLen) != 1)
474 {
475 log<level::DEBUG>("Hash genertion failed, bailing out");
476 return -EIO;
477 }
478 if (NULL == HMAC(digest, keyBuff.data(), keyBuff.size(), hash.data(),
479 hashLen, key.data(),
480 reinterpret_cast<unsigned int*>(&keyLen)))
481 {
482 log<level::DEBUG>("Failed to create MAC for authentication");
483 return -EIO;
484 }
485
486 // Generate IV values
487 if (RAND_bytes(iv.data(), ivLen) != 1)
488 {
489 log<level::DEBUG>("UV genertion failed, bailing out");
490 return -EIO;
491 }
492
493 // Encrypt the input data
494 std::vector<uint8_t> outBytes(inBytesLen + EVP_MAX_BLOCK_LENGTH);
495 size_t outBytesLen = 0;
496 if (inBytesLen != 0)
497 {
498 if (encryptDecryptData(true, EVP_aes_128_cbc(), key.data(), keyLen,
499 iv.data(), ivLen, inBytes.data(), inBytesLen,
500 mac.data(), &macLen, outBytes.data(),
501 &outBytesLen) != 0)
502 {
503 log<level::DEBUG>("Error while encrypting the data");
504 return -EIO;
505 }
506 outBytes[outBytesLen] = 0;
507 }
508 OPENSSL_cleanse(key.data(), keyLen);
509
510 // Update the meta password structure.
Richard Marian Thomaiyar48e55582018-12-20 15:58:04 +0530511 MetaPassStruct metaData = {META_PASSWD_SIG, {0, 0}, 0, 0, 0, 0, 0};
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530512 metaData.hashSize = hashLen;
513 metaData.ivSize = ivLen;
514 metaData.dataSize = bytesWritten;
515 metaData.padSize = outBytesLen - bytesWritten;
516 metaData.macSize = macLen;
517
518 if (fwrite(&metaData, 1, sizeof(metaData), (temp)()) != sizeof(metaData))
519 {
520 log<level::DEBUG>("Error in writing meta data");
521 return -EIO;
522 }
523
524 if (fwrite(&hash[0], 1, hashLen, (temp)()) != hashLen)
525 {
526 log<level::DEBUG>("Error in writing hash data");
527 return -EIO;
528 }
529
530 if (fwrite(&iv[0], 1, ivLen, (temp)()) != ivLen)
531 {
532 log<level::DEBUG>("Error in writing IV data");
533 return -EIO;
534 }
535
536 if (fwrite(&outBytes[0], 1, outBytesLen, (temp)()) != outBytesLen)
537 {
538 log<level::DEBUG>("Error in writing encrypted data");
539 return -EIO;
540 }
541
542 if (fwrite(&mac[0], 1, macLen, (temp)()) != macLen)
543 {
544 log<level::DEBUG>("Error in writing MAC data");
545 return -EIO;
546 }
547
548 if (fflush((temp)()))
549 {
550 log<level::DEBUG>(
551 "File fflush error while writing entries to special file");
552 return -EIO;
553 }
554
555 OPENSSL_cleanse(iv.data(), ivLen);
556
557 // Rename the tmp file to actual file
558 if (std::rename(strTempFileName.data(), passwdFileName) != 0)
559 {
560 log<level::DEBUG>("Failed to rename tmp file to ipmi-pass");
561 return -EIO;
562 }
563
564 return 0;
565}
566
567std::time_t PasswdMgr::getUpdatedFileTime()
568{
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530569 struct stat fileStat = {};
570 if (stat(passwdFileName, &fileStat) != 0)
571 {
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530572 log<level::DEBUG>("Error - Getting passwd file time stamp");
573 return -EIO;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530574 }
AppaRao Pulib29b5ab2018-05-17 10:28:48 +0530575 return fileStat.st_mtime;
Richard Marian Thomaiyar4654d992018-04-19 05:38:37 +0530576}
577
578} // namespace ipmi