From 8d2fad3c4c6a71691ab8c602c5396db1ba0de0f6 Mon Sep 17 00:00:00 2001 From: Stefan Gschiel Date: Wed, 15 Mar 2017 17:08:34 +0100 Subject: 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 --- nss-tool/common/util.cc | 53 ++++++++++++++++++++---- nss-tool/common/util.h | 1 + nss-tool/db/dbtool.cc | 107 ++++++++++++++++++++++++++++++++++++++++++++++-- nss-tool/db/dbtool.h | 2 + 4 files changed, 150 insertions(+), 13 deletions(-) (limited to 'nss-tool') 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 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(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 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 #include -const std::vector kCommandArgs({"--create", "--list-certs", - "--import-cert", "--list-keys", - "--import-key"}); +const std::vector 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 ]" << std::endl; std::cerr << " --create" << std::endl; + std::cerr << " --change-password" << std::endl; std::cerr << " --list-certs" << std::endl; std::cerr << " --import-cert [] --name [--trusts ]" << std::endl; std::cerr << " --list-keys" << std::endl; std::cerr << " --import-key [ [-- name ]]" << std::endl; + std::cerr << " --delete-cert " << std::endl; + std::cerr << " --delete-key " << std::endl; } bool DBTool::Run(const std::vector &arguments) { @@ -146,6 +150,12 @@ bool DBTool::Run(const std::vector &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(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__ -- cgit v1.2.1