michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* With the exception of GetPasswordString, this file was michael@0: copied from NSS's cmd/lib/secutil.c hg revision 8f011395145e */ michael@0: michael@0: #include "nss_secutil.h" michael@0: michael@0: #include "prprf.h" michael@0: #ifdef XP_WIN michael@0: #include michael@0: #else michael@0: #include michael@0: #endif michael@0: michael@0: static char consoleName[] = { michael@0: #ifdef XP_UNIX michael@0: "/dev/tty" michael@0: #else michael@0: "CON:" michael@0: #endif michael@0: }; michael@0: michael@0: #if defined(_WINDOWS) michael@0: static char * quiet_fgets (char *buf, int length, FILE *input) michael@0: { michael@0: int c; michael@0: char *end = buf; michael@0: michael@0: /* fflush (input); */ michael@0: memset (buf, 0, length); michael@0: michael@0: if (!isatty(fileno(input))) { michael@0: return fgets(buf,length,input); michael@0: } michael@0: michael@0: while (1) michael@0: { michael@0: #if defined (_WIN32_WCE) michael@0: c = getchar(); /* gets a character from stdin */ michael@0: #else michael@0: c = getch(); /* getch gets a character from the console */ michael@0: #endif michael@0: if (c == '\b') michael@0: { michael@0: if (end > buf) michael@0: end--; michael@0: } michael@0: michael@0: else if (--length > 0) michael@0: *end++ = c; michael@0: michael@0: if (!c || c == '\n' || c == '\r') michael@0: break; michael@0: } michael@0: michael@0: return buf; michael@0: } michael@0: #endif michael@0: michael@0: char * michael@0: GetPasswordString(void *arg, char *prompt) michael@0: { michael@0: FILE *input = stdin; michael@0: char phrase[200] = {'\0'}; michael@0: int isInputTerminal = isatty(fileno(stdin)); michael@0: michael@0: #ifndef _WINDOWS michael@0: if (isInputTerminal) { michael@0: input = fopen(consoleName, "r"); michael@0: if (input == NULL) { michael@0: fprintf(stderr, "Error opening input terminal for read\n"); michael@0: return NULL; michael@0: } michael@0: } michael@0: #endif michael@0: michael@0: if (isInputTerminal) { michael@0: fprintf(stdout, "Please enter your password:\n"); michael@0: fflush(stdout); michael@0: } michael@0: michael@0: QUIET_FGETS (phrase, sizeof(phrase), input); michael@0: michael@0: if (isInputTerminal) { michael@0: fprintf(stdout, "\n"); michael@0: } michael@0: michael@0: #ifndef _WINDOWS michael@0: if (isInputTerminal) { michael@0: fclose(input); michael@0: } michael@0: #endif michael@0: michael@0: /* Strip off the newlines if present */ michael@0: if (phrase[PORT_Strlen(phrase)-1] == '\n' || michael@0: phrase[PORT_Strlen(phrase)-1] == '\r') { michael@0: phrase[PORT_Strlen(phrase)-1] = 0; michael@0: } michael@0: return (char*) PORT_Strdup(phrase); michael@0: } michael@0: michael@0: char * michael@0: SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg) michael@0: { michael@0: char* phrases, *phrase; michael@0: PRFileDesc *fd; michael@0: int32_t nb; michael@0: char *pwFile = arg; michael@0: int i; michael@0: const long maxPwdFileSize = 4096; michael@0: char* tokenName = NULL; michael@0: int tokenLen = 0; michael@0: michael@0: if (!pwFile) michael@0: return 0; michael@0: michael@0: if (retry) { michael@0: return 0; /* no good retrying - the files contents will be the same */ michael@0: } michael@0: michael@0: phrases = PORT_ZAlloc(maxPwdFileSize); michael@0: michael@0: if (!phrases) { michael@0: return 0; /* out of memory */ michael@0: } michael@0: michael@0: fd = PR_Open(pwFile, PR_RDONLY, 0); michael@0: if (!fd) { michael@0: fprintf(stderr, "No password file \"%s\" exists.\n", pwFile); michael@0: PORT_Free(phrases); michael@0: return NULL; michael@0: } michael@0: michael@0: nb = PR_Read(fd, phrases, maxPwdFileSize); michael@0: michael@0: PR_Close(fd); michael@0: michael@0: if (nb == 0) { michael@0: fprintf(stderr,"password file contains no data\n"); michael@0: PORT_Free(phrases); michael@0: return NULL; michael@0: } michael@0: michael@0: if (slot) { michael@0: tokenName = PK11_GetTokenName(slot); michael@0: if (tokenName) { michael@0: tokenLen = PORT_Strlen(tokenName); michael@0: } michael@0: } michael@0: i = 0; michael@0: do michael@0: { michael@0: int startphrase = i; michael@0: int phraseLen; michael@0: michael@0: /* handle the Windows EOL case */ michael@0: while (phrases[i] != '\r' && phrases[i] != '\n' && i < nb) i++; michael@0: /* terminate passphrase */ michael@0: phrases[i++] = '\0'; michael@0: /* clean up any EOL before the start of the next passphrase */ michael@0: while ( (isource != PW_NONE) { michael@0: PR_fprintf(PR_STDERR, "Incorrect password/PIN entered.\n"); michael@0: return NULL; michael@0: } michael@0: michael@0: switch (pwdata->source) { michael@0: case PW_NONE: michael@0: sprintf(prompt, "Enter Password or Pin for \"%s\":", michael@0: PK11_GetTokenName(slot)); michael@0: return GetPasswordString(NULL, prompt); michael@0: case PW_FROMFILE: michael@0: /* Instead of opening and closing the file every time, get the pw michael@0: * once, then keep it in memory (duh). michael@0: */ michael@0: pw = SECU_FilePasswd(slot, retry, pwdata->data); michael@0: pwdata->source = PW_PLAINTEXT; michael@0: pwdata->data = PL_strdup(pw); michael@0: /* it's already been dup'ed */ michael@0: return pw; michael@0: case PW_EXTERNAL: michael@0: sprintf(prompt, michael@0: "Press Enter, then enter PIN for \"%s\" on external device.\n", michael@0: PK11_GetTokenName(slot)); michael@0: (void) GetPasswordString(NULL, prompt); michael@0: /* Fall Through */ michael@0: case PW_PLAINTEXT: michael@0: return PL_strdup(pwdata->data); michael@0: default: michael@0: break; michael@0: } michael@0: michael@0: PR_fprintf(PR_STDERR, "Password check failed: No password found.\n"); michael@0: return NULL; michael@0: }