/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "secutil.h" /* * NOTE: The contents of this file are NOT used by the client. * (They are part of the security library as a whole, but they are * NOT USED BY THE CLIENT.) Do not change things on behalf of the * client (like localizing strings), or add things that are only * for the client (put them elsewhere). */ #ifdef XP_UNIX #include #include /* for isatty() */ #endif #if defined(_WINDOWS) #include #include #define QUIET_FGETS quiet_fgets static char *quiet_fgets(char *buf, int length, FILE *input); #else #define QUIET_FGETS fgets #endif #if !defined(_WINDOWS) static void echoOff(int fd) { if (isatty(fd)) { struct termios tio; tcgetattr(fd, &tio); tio.c_lflag &= ~ECHO; tcsetattr(fd, TCSAFLUSH, &tio); } } static void echoOn(int fd) { if (isatty(fd)) { struct termios tio; tcgetattr(fd, &tio); tio.c_lflag |= ECHO; tcsetattr(fd, TCSAFLUSH, &tio); } } #endif char * SEC_GetPassword(FILE *input, FILE *output, char *prompt, PRBool (*ok)(char *)) { #if defined(_WINDOWS) int isTTY = (input == stdin); #define echoOn(x) #define echoOff(x) #else int infd = fileno(input); int isTTY = isatty(infd); #endif char phrase[500] = { '\0' }; /* ensure EOF doesn't return junk */ for (;;) { /* Prompt for password */ if (isTTY) { fprintf(output, "%s", prompt); fflush(output); echoOff(infd); } if (QUIET_FGETS(phrase, sizeof(phrase), input) == NULL) { return NULL; } if (isTTY) { fprintf(output, "\n"); echoOn(infd); } /* stomp on newline */ phrase[PORT_Strlen(phrase) - 1] = 0; /* Validate password */ if (!(*ok)(phrase)) { /* Not weird enough */ if (!isTTY) return NULL; fprintf(output, "Password must be at least 8 characters long with one or more\n"); fprintf(output, "non-alphabetic characters\n"); continue; } return (char *)PORT_Strdup(phrase); } } PRBool SEC_CheckPassword(char *cp) { int len; char *end; len = PORT_Strlen(cp); if (len < 8) { return PR_FALSE; } end = cp + len; while (cp < end) { unsigned char ch = *cp++; if (!((ch >= 'A') && (ch <= 'Z')) && !((ch >= 'a') && (ch <= 'z'))) { /* pass phrase has at least one non alphabetic in it */ return PR_TRUE; } } return PR_FALSE; } PRBool SEC_BlindCheckPassword(char *cp) { if (cp != NULL) { return PR_TRUE; } return PR_FALSE; } /* Get a password from the input terminal, without echoing */ #if defined(_WINDOWS) static char * quiet_fgets(char *buf, int length, FILE *input) { int c; char *end = buf; /* fflush (input); */ memset(buf, 0, length); if (!isatty(fileno(input))) { return fgets(buf, length, input); } while (1) { c = getch(); /* getch gets a character from the console */ if (c == '\b') { if (end > buf) end--; } else if (--length > 0) *end++ = c; if (!c || c == '\n' || c == '\r') break; } return buf; } #endif