summaryrefslogtreecommitdiffstats
path: root/security/nss/nss-tool/common
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/nss-tool/common')
-rw-r--r--security/nss/nss-tool/common/argparse.cc23
-rw-r--r--security/nss/nss-tool/common/argparse.h30
-rw-r--r--security/nss/nss-tool/common/tool.h20
-rw-r--r--security/nss/nss-tool/common/util.cc216
-rw-r--r--security/nss/nss-tool/common/util.h32
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 000000000..3b7c73891
--- /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 000000000..8645d5aaa
--- /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 000000000..17ebcac29
--- /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 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;
+}
diff --git a/security/nss/nss-tool/common/util.h b/security/nss/nss-tool/common/util.h
new file mode 100644
index 000000000..58fb05839
--- /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 "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__