diff options
Diffstat (limited to 'security/nss/nss-tool/common')
-rw-r--r-- | security/nss/nss-tool/common/argparse.cc | 23 | ||||
-rw-r--r-- | security/nss/nss-tool/common/argparse.h | 30 | ||||
-rw-r--r-- | security/nss/nss-tool/common/tool.h | 20 | ||||
-rw-r--r-- | security/nss/nss-tool/common/util.cc | 216 | ||||
-rw-r--r-- | security/nss/nss-tool/common/util.h | 32 |
5 files changed, 321 insertions, 0 deletions
diff --git a/security/nss/nss-tool/common/argparse.cc b/security/nss/nss-tool/common/argparse.cc new file mode 100644 index 0000000000..3b7c73891c --- /dev/null +++ b/security/nss/nss-tool/common/argparse.cc @@ -0,0 +1,23 @@ +/* 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 "argparse.h" + +ArgParser::ArgParser(const std::vector<std::string>& arguments) { + for (size_t i = 0; i < arguments.size(); i++) { + std::string arg = arguments.at(i); + if (arg.find("--") == 0) { + // look for an option argument + if (i + 1 < arguments.size() && arguments.at(i + 1).find("--") != 0) { + programArgs_[arg] = arguments.at(i + 1); + i++; + } else { + programArgs_[arg] = ""; + } + } else { + // positional argument (e.g. required argument) + positionalArgs_.push_back(arg); + } + } +} diff --git a/security/nss/nss-tool/common/argparse.h b/security/nss/nss-tool/common/argparse.h new file mode 100644 index 0000000000..8645d5aaa6 --- /dev/null +++ b/security/nss/nss-tool/common/argparse.h @@ -0,0 +1,30 @@ +/* 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/. */ + +#ifndef argparse_h__ +#define argparse_h__ + +#include <string> +#include <unordered_map> +#include <vector> + +class ArgParser { + public: + ArgParser(const std::vector<std::string>& arguments); + + bool Has(std::string arg) const { return programArgs_.count(arg) > 0; } + + std::string Get(std::string arg) const { return programArgs_.at(arg); } + + size_t GetPositionalArgumentCount() const { return positionalArgs_.size(); } + std::string GetPositionalArgument(size_t pos) const { + return positionalArgs_.at(pos); + } + + private: + std::unordered_map<std::string, std::string> programArgs_; + std::vector<std::string> positionalArgs_; +}; + +#endif // argparse_h__ diff --git a/security/nss/nss-tool/common/tool.h b/security/nss/nss-tool/common/tool.h new file mode 100644 index 0000000000..17ebcac29b --- /dev/null +++ b/security/nss/nss-tool/common/tool.h @@ -0,0 +1,20 @@ +/* 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/. */ + +#ifndef tool_h__ +#define tool_h__ + +#include <string> +#include <vector> + +class Tool { + public: + virtual bool Run(const std::vector<std::string>& arguments) = 0; + virtual ~Tool() {} + + private: + virtual void Usage() = 0; +}; + +#endif // tool_h__ diff --git a/security/nss/nss-tool/common/util.cc b/security/nss/nss-tool/common/util.cc new file mode 100644 index 0000000000..77459155a5 --- /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; +} diff --git a/security/nss/nss-tool/common/util.h b/security/nss/nss-tool/common/util.h new file mode 100644 index 0000000000..e7076336b6 --- /dev/null +++ b/security/nss/nss-tool/common/util.h @@ -0,0 +1,32 @@ +/* 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/. */ + +#ifndef util_h__ +#define util_h__ + +#include "nspr.h" +#include "nss_scoped_ptrs.h" + +#include <secmodt.h> +#include <string> +#include <vector> + +#ifndef PORT_Malloc +#define PORT_Malloc PR_Malloc +#endif + +enum PwDataType { PW_NONE = 0, PW_FROMFILE = 1, PW_PLAINTEXT = 2 }; +typedef struct { + PwDataType source; + char *data; +} PwData; + +bool InitSlotPassword(void); +bool ChangeSlotPassword(void); +bool DBLoginIfNeeded(const ScopedPK11SlotInfo &slot); +std::string StringToHex(const ScopedSECItem &input); +std::vector<uint8_t> ReadInputData(std::string dataPath); +std::istream &GetStreamFromFileOrStdin(std::string &path, std::ifstream &ifs); + +#endif // util_h__ |