tor-browser

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

nss_secutil.c (5445B)


      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 /* With the exception of GetPasswordString, this file was
      6   copied from NSS's cmd/lib/secutil.c hg revision 8f011395145e */
      7 
      8 #include "nss_secutil.h"
      9 
     10 #include "prprf.h"
     11 #ifdef XP_WIN
     12 #  include <io.h>
     13 #else
     14 #  include <unistd.h>
     15 #endif
     16 
     17 #if defined(_WINDOWS)
     18 char* quiet_fgets(char* buf, int length, FILE* input) {
     19  int c;
     20  char* end = buf;
     21 
     22  /* fflush (input); */
     23  memset(buf, 0, length);
     24 
     25  if (!isatty(fileno(input))) {
     26    return fgets(buf, length, input);
     27  }
     28 
     29  while (1) {
     30 #  if defined(_WIN32_WCE)
     31    c = getchar(); /* gets a character from stdin */
     32 #  else
     33    c = getch(); /* getch gets a character from the console */
     34 #  endif
     35    if (c == '\b') {
     36      if (end > buf) end--;
     37    }
     38 
     39    else if (--length > 0)
     40      *end++ = c;
     41 
     42    if (!c || c == '\n' || c == '\r') break;
     43  }
     44 
     45  return buf;
     46 }
     47 #endif
     48 
     49 char* GetPasswordString(void* arg, char* prompt) {
     50  FILE* input = stdin;
     51  char phrase[200] = {'\0'};
     52  int isInputTerminal = isatty(fileno(stdin));
     53 
     54 #ifndef _WINDOWS
     55  if (isInputTerminal) {
     56    static char consoleName[] = {
     57 #  ifdef XP_UNIX
     58        "/dev/tty"
     59 #  else
     60        "CON:"
     61 #  endif
     62    };
     63 
     64    input = fopen(consoleName, "r");
     65    if (input == NULL) {
     66      fprintf(stderr, "Error opening input terminal for read\n");
     67      return NULL;
     68    }
     69  }
     70 #endif
     71 
     72  if (isInputTerminal) {
     73    fprintf(stdout, "Please enter your password:\n");
     74    fflush(stdout);
     75  }
     76 
     77  if (!QUIET_FGETS(phrase, sizeof(phrase), input)) {
     78    fprintf(stderr, "QUIET_FGETS failed\n");
     79 #ifndef _WINDOWS
     80    if (isInputTerminal) {
     81      fclose(input);
     82    }
     83 #endif
     84    return NULL;
     85  }
     86 
     87  if (isInputTerminal) {
     88    fprintf(stdout, "\n");
     89  }
     90 
     91 #ifndef _WINDOWS
     92  if (isInputTerminal) {
     93    fclose(input);
     94  }
     95 #endif
     96 
     97  /* Strip off the newlines if present */
     98  if (phrase[PORT_Strlen(phrase) - 1] == '\n' ||
     99      phrase[PORT_Strlen(phrase) - 1] == '\r') {
    100    phrase[PORT_Strlen(phrase) - 1] = 0;
    101  }
    102  return (char*)PORT_Strdup(phrase);
    103 }
    104 
    105 char* SECU_FilePasswd(PK11SlotInfo* slot, PRBool retry, void* arg) {
    106  char *phrases, *phrase;
    107  PRFileDesc* fd;
    108  int32_t nb;
    109  char* pwFile = arg;
    110  int i;
    111  const long maxPwdFileSize = 4096;
    112  char* tokenName = NULL;
    113  int tokenLen = 0;
    114 
    115  if (!pwFile) return 0;
    116 
    117  if (retry) {
    118    return 0; /* no good retrying - the files contents will be the same */
    119  }
    120 
    121  phrases = PORT_ZAlloc(maxPwdFileSize);
    122 
    123  if (!phrases) {
    124    return 0; /* out of memory */
    125  }
    126 
    127  fd = PR_Open(pwFile, PR_RDONLY, 0);
    128  if (!fd) {
    129    fprintf(stderr, "No password file \"%s\" exists.\n", pwFile);
    130    PORT_Free(phrases);
    131    return NULL;
    132  }
    133 
    134  nb = PR_Read(fd, phrases, maxPwdFileSize);
    135 
    136  PR_Close(fd);
    137 
    138  if (nb == 0) {
    139    fprintf(stderr, "password file contains no data\n");
    140    PORT_Free(phrases);
    141    return NULL;
    142  }
    143 
    144  if (slot) {
    145    tokenName = PK11_GetTokenName(slot);
    146    if (tokenName) {
    147      tokenLen = PORT_Strlen(tokenName);
    148    }
    149  }
    150  i = 0;
    151  do {
    152    int startphrase = i;
    153    int phraseLen;
    154 
    155    /* handle the Windows EOL case */
    156    while (phrases[i] != '\r' && phrases[i] != '\n' && i < nb) i++;
    157    /* terminate passphrase */
    158    if (i < nb) {
    159      phrases[i++] = '\0';
    160    }
    161    /* clean up any EOL before the start of the next passphrase */
    162    while ((i < nb) && (phrases[i] == '\r' || phrases[i] == '\n')) {
    163      phrases[i++] = '\0';
    164    }
    165    /* now analyze the current passphrase */
    166    phrase = &phrases[startphrase];
    167    if (!tokenName) break;
    168    if (PORT_Strncmp(phrase, tokenName, tokenLen)) continue;
    169    phraseLen = PORT_Strlen(phrase);
    170    if (phraseLen < (tokenLen + 1)) continue;
    171    if (phrase[tokenLen] != ':') continue;
    172    phrase = &phrase[tokenLen + 1];
    173    break;
    174 
    175  } while (i < nb);
    176 
    177  phrase = PORT_Strdup((char*)phrase);
    178  PORT_Free(phrases);
    179  return phrase;
    180 }
    181 
    182 char* SECU_GetModulePassword(PK11SlotInfo* slot, PRBool retry, void* arg) {
    183  char prompt[255];
    184  secuPWData* pwdata = (secuPWData*)arg;
    185  secuPWData pwnull = {PW_NONE, 0};
    186  secuPWData pwxtrn = {PW_EXTERNAL, "external"};
    187  char* pw;
    188 
    189  if (pwdata == NULL) pwdata = &pwnull;
    190 
    191  if (PK11_ProtectedAuthenticationPath(slot)) {
    192    pwdata = &pwxtrn;
    193  }
    194  if (retry && pwdata->source != PW_NONE) {
    195    PR_fprintf(PR_STDERR, "Incorrect password/PIN entered.\n");
    196    return NULL;
    197  }
    198 
    199  switch (pwdata->source) {
    200    case PW_NONE:
    201      sprintf(prompt,
    202              "Enter Password or Pin for \"%s\":", PK11_GetTokenName(slot));
    203      return GetPasswordString(NULL, prompt);
    204    case PW_FROMFILE:
    205      /* Instead of opening and closing the file every time, get the pw
    206       * once, then keep it in memory (duh).
    207       */
    208      pw = SECU_FilePasswd(slot, retry, pwdata->data);
    209      pwdata->source = PW_PLAINTEXT;
    210      pwdata->data = strdup(pw);
    211      /* it's already been dup'ed */
    212      return pw;
    213    case PW_EXTERNAL:
    214      sprintf(prompt,
    215              "Press Enter, then enter PIN for \"%s\" on external device.\n",
    216              PK11_GetTokenName(slot));
    217      pw = GetPasswordString(NULL, prompt);
    218      if (pw) {
    219        memset(pw, 0, PORT_Strlen(pw));
    220        PORT_Free(pw);
    221      }
    222      /* Fall Through */
    223    case PW_PLAINTEXT:
    224      return strdup(pwdata->data);
    225    default:
    226      break;
    227  }
    228 
    229  PR_fprintf(PR_STDERR, "Password check failed:  No password found.\n");
    230  return NULL;
    231 }