summaryrefslogtreecommitdiff
path: root/nss-tool
diff options
context:
space:
mode:
authorStefan Gschiel <stefan.gschiel.sg@gmail.com>2017-03-15 17:08:34 +0100
committerStefan Gschiel <stefan.gschiel.sg@gmail.com>2017-03-15 17:08:34 +0100
commit8d2fad3c4c6a71691ab8c602c5396db1ba0de0f6 (patch)
tree9fe4fb4fa987420d424eca7f6be298f725f61616 /nss-tool
parentf934ffb318d05812fcdc8fcf8a434b00fe5363e2 (diff)
downloadnss-hg-8d2fad3c4c6a71691ab8c602c5396db1ba0de0f6.tar.gz
Bug 1347613 - nss-tool: allow removing certs and keys from a DB, changing a DB password r=ttaubert
Differential Revision: https://nss-review.dev.mozaws.net/D247
Diffstat (limited to 'nss-tool')
-rw-r--r--nss-tool/common/util.cc53
-rw-r--r--nss-tool/common/util.h1
-rw-r--r--nss-tool/db/dbtool.cc107
-rw-r--r--nss-tool/db/dbtool.h2
4 files changed, 150 insertions, 13 deletions
diff --git a/nss-tool/common/util.cc b/nss-tool/common/util.cc
index 7cc4352c6..5b7ed0b9d 100644
--- a/nss-tool/common/util.cc
+++ b/nss-tool/common/util.cc
@@ -85,6 +85,21 @@ static std::vector<char> ReadFromIstream(std::istream &is) {
return certData;
}
+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) {
@@ -95,23 +110,43 @@ bool InitSlotPassword(void) {
std::cout << "Enter a password which will be used to encrypt your keys."
<< std::endl
<< std::endl;
- std::string pw;
+ std::string pw = GetNewPasswordFromUser();
- while (true) {
- pw = GetPassword("Enter new password: ");
- if (pw == GetPassword("Re-enter password: ")) {
- break;
- }
+ SECStatus rv = PK11_InitPin(slot.get(), nullptr, pw.c_str());
+ if (rv != SECSuccess) {
+ std::cerr << "Init db password failed." << std::endl;
+ return false;
+ }
- std::cerr << "Passwords do not match. Try again." << std::endl;
+ return true;
+}
+
+bool ChangeSlotPassword(void) {
+ ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
+ if (slot.get() == nullptr) {
+ std::cerr << "Error: Init PK11SlotInfo failed!" << std::endl;
+ return false;
}
- SECStatus rv = PK11_InitPin(slot.get(), nullptr, pw.c_str());
+ // 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 << "Init db password failed." << std::endl;
+ 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;
}
diff --git a/nss-tool/common/util.h b/nss-tool/common/util.h
index 8b3b0f11e..bfe6dbf70 100644
--- a/nss-tool/common/util.h
+++ b/nss-tool/common/util.h
@@ -18,6 +18,7 @@ typedef struct {
} PwData;
bool InitSlotPassword(void);
+bool ChangeSlotPassword(void);
bool DBLoginIfNeeded(const ScopedPK11SlotInfo &slot);
std::string StringToHex(const ScopedSECItem &input);
std::vector<char> ReadInputData(std::string &dataPath);
diff --git a/nss-tool/db/dbtool.cc b/nss-tool/db/dbtool.cc
index f1d1b0edd..e48cedec8 100644
--- a/nss-tool/db/dbtool.cc
+++ b/nss-tool/db/dbtool.cc
@@ -20,9 +20,9 @@
#include <prerror.h>
#include <prio.h>
-const std::vector<std::string> kCommandArgs({"--create", "--list-certs",
- "--import-cert", "--list-keys",
- "--import-key"});
+const std::vector<std::string> kCommandArgs(
+ {"--create", "--list-certs", "--import-cert", "--list-keys", "--import-key",
+ "--delete-cert", "--delete-key", "--change-password"});
static bool HasSingleCommandArgument(const ArgParser &parser) {
auto pred = [&](const std::string &cmd) { return parser.Has(cmd); };
@@ -31,7 +31,8 @@ static bool HasSingleCommandArgument(const ArgParser &parser) {
static bool HasArgumentRequiringWriteAccess(const ArgParser &parser) {
return parser.Has("--create") || parser.Has("--import-cert") ||
- parser.Has("--import-key");
+ parser.Has("--import-key") || parser.Has("--delete-cert") ||
+ parser.Has("--delete-key") || parser.Has("--change-password");
}
static std::string PrintFlags(unsigned int flags) {
@@ -73,11 +74,14 @@ static const char *const keyTypeName[] = {"null", "rsa", "dsa", "fortezza",
void DBTool::Usage() {
std::cerr << "Usage: nss db [--path <directory>]" << std::endl;
std::cerr << " --create" << std::endl;
+ std::cerr << " --change-password" << std::endl;
std::cerr << " --list-certs" << std::endl;
std::cerr << " --import-cert [<path>] --name <name> [--trusts <trusts>]"
<< std::endl;
std::cerr << " --list-keys" << std::endl;
std::cerr << " --import-key [<path> [-- name <name>]]" << std::endl;
+ std::cerr << " --delete-cert <name>" << std::endl;
+ std::cerr << " --delete-key <name>" << std::endl;
}
bool DBTool::Run(const std::vector<std::string> &arguments) {
@@ -146,6 +150,12 @@ bool DBTool::Run(const std::vector<std::string> &arguments) {
ret = ListKeys();
} else if (parser.Has("--import-key")) {
ret = ImportKey(parser);
+ } else if (parser.Has("--delete-cert")) {
+ ret = DeleteCert(parser);
+ } else if (parser.Has("--delete-key")) {
+ ret = DeleteKey(parser);
+ } else if (parser.Has("--change-password")) {
+ ret = ChangeSlotPassword();
}
// shutdown nss
@@ -397,3 +407,92 @@ bool DBTool::ImportKey(const ArgParser &parser) {
std::cout << "Key import succeeded." << std::endl;
return true;
}
+
+bool DBTool::DeleteCert(const ArgParser &parser) {
+ std::string certName = parser.Get("--delete-cert");
+ if (certName.empty()) {
+ std::cerr << "A name is required to delete a certificate." << std::endl;
+ Usage();
+ return false;
+ }
+
+ ScopedCERTCertificate cert(CERT_FindCertByNicknameOrEmailAddr(
+ CERT_GetDefaultCertDB(), certName.c_str()));
+ if (!cert) {
+ std::cerr << "Could not find certificate with name " << certName << "."
+ << std::endl;
+ return false;
+ }
+
+ SECStatus rv = SEC_DeletePermCertificate(cert.get());
+ if (rv != SECSuccess) {
+ std::cerr << "Unable to delete certificate with name " << certName << "."
+ << std::endl;
+ return false;
+ }
+
+ std::cout << "Certificate with name " << certName << " deleted successfully."
+ << std::endl;
+ return true;
+}
+
+bool DBTool::DeleteKey(const ArgParser &parser) {
+ std::string keyName = parser.Get("--delete-key");
+ if (keyName.empty()) {
+ std::cerr << "A name is required to delete a key." << std::endl;
+ Usage();
+ return false;
+ }
+
+ ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
+ if (slot.get() == nullptr) {
+ std::cerr << "Error: Init PK11SlotInfo failed!" << std::endl;
+ return false;
+ }
+
+ if (!DBLoginIfNeeded(slot)) {
+ return false;
+ }
+
+ ScopedSECKEYPrivateKeyList list(PK11_ListPrivKeysInSlot(
+ slot.get(), const_cast<char *>(keyName.c_str()), nullptr));
+ if (list.get() == nullptr) {
+ std::cerr << "Fetching private keys with nickname " << keyName
+ << " failed with error " << PR_ErrorToName(PR_GetError())
+ << std::endl;
+ return false;
+ }
+
+ unsigned int foundKeys = 0, deletedKeys = 0;
+ SECKEYPrivateKeyListNode *node;
+ for (node = PRIVKEY_LIST_HEAD(list.get());
+ !PRIVKEY_LIST_END(node, list.get()); node = PRIVKEY_LIST_NEXT(node)) {
+ SECKEYPrivateKey *privKey = node->key;
+ foundKeys++;
+ // see PK11_DeleteTokenPrivateKey for example usage
+ // calling PK11_DeleteTokenPrivateKey directly does not work because it also
+ // destroys the SECKEYPrivateKey (by calling SECKEY_DestroyPrivateKey) -
+ // then SECKEY_DestroyPrivateKeyList does not
+ // work because it also calls SECKEY_DestroyPrivateKey
+ SECStatus rv =
+ PK11_DestroyTokenObject(privKey->pkcs11Slot, privKey->pkcs11ID);
+ if (rv == SECSuccess) {
+ deletedKeys++;
+ }
+ }
+
+ if (foundKeys > deletedKeys) {
+ std::cerr << "Some keys could not be deleted." << std::endl;
+ }
+
+ if (deletedKeys > 0) {
+ std::cout << "Found " << foundKeys << " keys." << std::endl;
+ std::cout << "Successfully deleted " << deletedKeys
+ << " key(s) with nickname " << keyName << "." << std::endl;
+ } else {
+ std::cout << "No key with nickname " << keyName << " found to delete."
+ << std::endl;
+ }
+
+ return true;
+}
diff --git a/nss-tool/db/dbtool.h b/nss-tool/db/dbtool.h
index 9d5ddedb2..927afa9f8 100644
--- a/nss-tool/db/dbtool.h
+++ b/nss-tool/db/dbtool.h
@@ -20,6 +20,8 @@ class DBTool {
bool ImportCertificate(const ArgParser& parser);
bool ListKeys();
bool ImportKey(const ArgParser& parser);
+ bool DeleteCert(const ArgParser& parser);
+ bool DeleteKey(const ArgParser& parser);
};
#endif // dbtool_h__