tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }