diff options
Diffstat (limited to 'security/nss/nss-tool/common/util.cc')
-rw-r--r-- | security/nss/nss-tool/common/util.cc | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/security/nss/nss-tool/common/util.cc b/security/nss/nss-tool/common/util.cc new file mode 100644 index 000000000..77459155a --- /dev/null +++ b/security/nss/nss-tool/common/util.cc @@ -0,0 +1,216 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "util.h" + +#include <fstream> +#include <iomanip> +#include <iostream> +#include <sstream> +#include <string> + +#include <prerror.h> + +#if defined(__unix__) || defined(__APPLE__) +#include <termios.h> +#include <unistd.h> +#elif defined(WIN32) || defined(_WIN64) +#include <Windows.h> +#endif + +static std::string GetPassword(const std::string &prompt) { + std::cout << prompt << std::endl; + +#if defined(__unix__) || defined(__APPLE__) + termios oldt; + tcgetattr(STDIN_FILENO, &oldt); + termios newt = oldt; + newt.c_lflag &= ~ECHO; + tcsetattr(STDIN_FILENO, TCSANOW, &newt); +#elif defined(WIN32) || defined(_WIN64) + HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); + DWORD mode = 0; + GetConsoleMode(hStdin, &mode); + SetConsoleMode(hStdin, mode & (~ENABLE_ECHO_INPUT)); +#endif + + std::string pw; + std::getline(std::cin, pw); + +#if defined(__unix__) || defined(__APPLE__) + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); +#elif defined(WIN32) || defined(_WIN64) + SetConsoleMode(hStdin, mode); +#endif + + return pw; +} + +static char *GetModulePassword(PK11SlotInfo *slot, int retry, void *arg) { + if (arg == nullptr) { + return nullptr; + } + + PwData *pwData = reinterpret_cast<PwData *>(arg); + + if (retry > 0) { + std::cerr << "Incorrect password/PIN entered." << std::endl; + return nullptr; + } + + switch (pwData->source) { + case PW_NONE: + case PW_FROMFILE: + std::cerr << "Password input method not supported." << std::endl; + return nullptr; + case PW_PLAINTEXT: + return PL_strdup(pwData->data); + default: + break; + } + + std::cerr << "Password check failed: No password found." << std::endl; + return nullptr; +} + +static std::vector<uint8_t> ReadFromIstream(std::istream &is) { + std::vector<uint8_t> data; + while (is) { + char buf[1024]; + is.read(buf, sizeof(buf)); + data.insert(data.end(), buf, buf + is.gcount()); + } + + return data; +} + +static std::string GetNewPasswordFromUser(void) { + std::string pw; + + while (true) { + pw = GetPassword("Enter new password: "); + if (pw == GetPassword("Re-enter password: ")) { + break; + } + + std::cerr << "Passwords do not match. Try again." << std::endl; + } + + return pw; +} + +bool InitSlotPassword(void) { + ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); + if (slot.get() == nullptr) { + std::cerr << "Error: Init PK11SlotInfo failed!" << std::endl; + return false; + } + + std::cout << "Enter a password which will be used to encrypt your keys." + << std::endl + << std::endl; + std::string pw = GetNewPasswordFromUser(); + + SECStatus rv = PK11_InitPin(slot.get(), nullptr, pw.c_str()); + if (rv != SECSuccess) { + std::cerr << "Init db password failed." << std::endl; + return false; + } + + return true; +} + +bool ChangeSlotPassword(void) { + ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); + if (slot.get() == nullptr) { + std::cerr << "Error: Init PK11SlotInfo failed!" << std::endl; + return false; + } + + // get old password and authenticate to db + PK11_SetPasswordFunc(&GetModulePassword); + std::string oldPw = GetPassword("Enter your current password: "); + PwData pwData = {PW_PLAINTEXT, const_cast<char *>(oldPw.c_str())}; + SECStatus rv = PK11_Authenticate(slot.get(), false /*loadCerts*/, &pwData); + if (rv != SECSuccess) { + std::cerr << "Password incorrect." << std::endl; + return false; + } + + // get new password + std::string newPw = GetNewPasswordFromUser(); + + if (PK11_ChangePW(slot.get(), oldPw.c_str(), newPw.c_str()) != SECSuccess) { + std::cerr << "Failed to change password." << std::endl; + return false; + } + + std::cout << "Password changed successfully." << std::endl; + return true; +} + +bool DBLoginIfNeeded(const ScopedPK11SlotInfo &slot) { + if (!PK11_NeedLogin(slot.get())) { + return true; + } + + PK11_SetPasswordFunc(&GetModulePassword); + std::string pw = GetPassword("Enter your password: "); + PwData pwData = {PW_PLAINTEXT, const_cast<char *>(pw.c_str())}; + SECStatus rv = PK11_Authenticate(slot.get(), true /*loadCerts*/, &pwData); + if (rv != SECSuccess) { + std::cerr << "Could not authenticate to token " + << PK11_GetTokenName(slot.get()) << ". Failed with error " + << PR_ErrorToName(PR_GetError()) << std::endl; + return false; + } + std::cout << std::endl; + + return true; +} + +std::string StringToHex(const ScopedSECItem &input) { + std::stringstream ss; + ss << "0x"; + for (size_t i = 0; i < input->len; i++) { + ss << std::hex << std::setfill('0') << std::setw(2) + << static_cast<int>(input->data[i]); + } + + return ss.str(); +} + +std::vector<uint8_t> ReadInputData(std::string dataPath) { + std::vector<uint8_t> data; + if (dataPath.empty()) { + std::cout << "No input file path given, using stdin." << std::endl; + data = ReadFromIstream(std::cin); + } else { + std::ifstream is(dataPath, std::ifstream::binary); + if (is.good()) { + data = ReadFromIstream(is); + } else { + std::cerr << "IO Error when opening " << dataPath << std::endl; + std::cerr << "Input file does not exist or you don't have permissions." + << std::endl; + } + } + + return data; +} + +std::istream &GetStreamFromFileOrStdin(std::string &path, std::ifstream &ifs) { + if (path.empty()) { + return std::cin; + } + + ifs.open(path, std::ifstream::binary); + if (!ifs.good()) { + std::cerr << "IO Error when opening " << path << std::endl; + std::cerr << "Input file does not exist or you don't have permissions." + << std::endl; + } + + return ifs; +} |