util.cc (5712B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "util.h" 6 7 #include <fstream> 8 #include <iomanip> 9 #include <iostream> 10 #include <sstream> 11 #include <string> 12 13 #include <prerror.h> 14 15 #if defined(__unix__) || defined(__APPLE__) 16 #include <termios.h> 17 #include <unistd.h> 18 #elif defined(WIN32) || defined(_WIN64) 19 #include <Windows.h> 20 #endif 21 22 static std::string GetPassword(const std::string &prompt) { 23 std::cout << prompt << std::endl; 24 25 #if defined(__unix__) || defined(__APPLE__) 26 termios oldt; 27 tcgetattr(STDIN_FILENO, &oldt); 28 termios newt = oldt; 29 newt.c_lflag &= ~ECHO; 30 tcsetattr(STDIN_FILENO, TCSANOW, &newt); 31 #elif defined(WIN32) || defined(_WIN64) 32 HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); 33 DWORD mode = 0; 34 GetConsoleMode(hStdin, &mode); 35 SetConsoleMode(hStdin, mode & (~ENABLE_ECHO_INPUT)); 36 #endif 37 38 std::string pw; 39 std::getline(std::cin, pw); 40 41 #if defined(__unix__) || defined(__APPLE__) 42 tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 43 #elif defined(WIN32) || defined(_WIN64) 44 SetConsoleMode(hStdin, mode); 45 #endif 46 47 return pw; 48 } 49 50 static char *GetModulePassword(PK11SlotInfo *slot, int retry, void *arg) { 51 if (arg == nullptr) { 52 return nullptr; 53 } 54 55 PwData *pwData = reinterpret_cast<PwData *>(arg); 56 57 if (retry > 0) { 58 std::cerr << "Incorrect password/PIN entered." << std::endl; 59 return nullptr; 60 } 61 62 switch (pwData->source) { 63 case PW_NONE: 64 case PW_FROMFILE: 65 std::cerr << "Password input method not supported." << std::endl; 66 return nullptr; 67 case PW_PLAINTEXT: 68 return PL_strdup(pwData->data); 69 default: 70 break; 71 } 72 73 std::cerr << "Password check failed: No password found." << std::endl; 74 return nullptr; 75 } 76 77 static std::vector<uint8_t> ReadFromIstream(std::istream &is) { 78 std::vector<uint8_t> data; 79 while (is) { 80 char buf[1024]; 81 is.read(buf, sizeof(buf)); 82 data.insert(data.end(), buf, buf + is.gcount()); 83 } 84 85 return data; 86 } 87 88 static std::string GetNewPasswordFromUser(void) { 89 std::string pw; 90 91 while (true) { 92 pw = GetPassword("Enter new password: "); 93 if (pw == GetPassword("Re-enter password: ")) { 94 break; 95 } 96 97 std::cerr << "Passwords do not match. Try again." << std::endl; 98 } 99 100 return pw; 101 } 102 103 bool InitSlotPassword(void) { 104 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 105 if (slot.get() == nullptr) { 106 std::cerr << "Error: Init PK11SlotInfo failed!" << std::endl; 107 return false; 108 } 109 110 std::cout << "Enter a password which will be used to encrypt your keys." 111 << std::endl 112 << std::endl; 113 std::string pw = GetNewPasswordFromUser(); 114 115 SECStatus rv = PK11_InitPin(slot.get(), nullptr, pw.c_str()); 116 if (rv != SECSuccess) { 117 std::cerr << "Init db password failed." << std::endl; 118 return false; 119 } 120 121 return true; 122 } 123 124 bool ChangeSlotPassword(void) { 125 ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot()); 126 if (slot.get() == nullptr) { 127 std::cerr << "Error: Init PK11SlotInfo failed!" << std::endl; 128 return false; 129 } 130 131 // get old password and authenticate to db 132 PK11_SetPasswordFunc(&GetModulePassword); 133 std::string oldPw = GetPassword("Enter your current password: "); 134 PwData pwData = {PW_PLAINTEXT, const_cast<char *>(oldPw.c_str())}; 135 SECStatus rv = PK11_Authenticate(slot.get(), false /*loadCerts*/, &pwData); 136 if (rv != SECSuccess) { 137 std::cerr << "Password incorrect." << std::endl; 138 return false; 139 } 140 141 // get new password 142 std::string newPw = GetNewPasswordFromUser(); 143 144 if (PK11_ChangePW(slot.get(), oldPw.c_str(), newPw.c_str()) != SECSuccess) { 145 std::cerr << "Failed to change password." << std::endl; 146 return false; 147 } 148 149 std::cout << "Password changed successfully." << std::endl; 150 return true; 151 } 152 153 bool DBLoginIfNeeded(const ScopedPK11SlotInfo &slot) { 154 if (!PK11_NeedLogin(slot.get())) { 155 return true; 156 } 157 158 PK11_SetPasswordFunc(&GetModulePassword); 159 std::string pw = GetPassword("Enter your password: "); 160 PwData pwData = {PW_PLAINTEXT, const_cast<char *>(pw.c_str())}; 161 SECStatus rv = PK11_Authenticate(slot.get(), true /*loadCerts*/, &pwData); 162 if (rv != SECSuccess) { 163 std::cerr << "Could not authenticate to token " 164 << PK11_GetTokenName(slot.get()) << ". Failed with error " 165 << PR_ErrorToName(PR_GetError()) << std::endl; 166 return false; 167 } 168 std::cout << std::endl; 169 170 return true; 171 } 172 173 std::string StringToHex(const ScopedSECItem &input) { 174 std::stringstream ss; 175 ss << "0x"; 176 for (size_t i = 0; i < input->len; i++) { 177 ss << std::hex << std::setfill('0') << std::setw(2) 178 << static_cast<int>(input->data[i]); 179 } 180 181 return ss.str(); 182 } 183 184 std::vector<uint8_t> ReadInputData(std::string dataPath) { 185 std::vector<uint8_t> data; 186 if (dataPath.empty()) { 187 std::cout << "No input file path given, using stdin." << std::endl; 188 data = ReadFromIstream(std::cin); 189 } else { 190 std::ifstream is(dataPath, std::ifstream::binary); 191 if (is.good()) { 192 data = ReadFromIstream(is); 193 } else { 194 std::cerr << "IO Error when opening " << dataPath << std::endl; 195 std::cerr << "Input file does not exist or you don't have permissions." 196 << std::endl; 197 } 198 } 199 200 return data; 201 } 202 203 std::istream &GetStreamFromFileOrStdin(std::string &path, std::ifstream &ifs) { 204 if (path.empty()) { 205 return std::cin; 206 } 207 208 ifs.open(path, std::ifstream::binary); 209 if (!ifs.good()) { 210 std::cerr << "IO Error when opening " << path << std::endl; 211 std::cerr << "Input file does not exist or you don't have permissions." 212 << std::endl; 213 } 214 215 return ifs; 216 }