secpwd.c (3601B)
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 #include "secutil.h" 5 6 /* 7 * NOTE: The contents of this file are NOT used by the client. 8 * (They are part of the security library as a whole, but they are 9 * NOT USED BY THE CLIENT.) Do not change things on behalf of the 10 * client (like localizing strings), or add things that are only 11 * for the client (put them elsewhere). 12 */ 13 14 #ifdef XP_UNIX 15 #include <termios.h> 16 #include <unistd.h> /* for isatty() */ 17 #endif 18 19 #if defined(_WINDOWS) 20 #include <conio.h> 21 #include <io.h> 22 #define QUIET_FGETS quiet_fgets 23 static char *quiet_fgets(char *buf, int length, FILE *input); 24 #else 25 #define QUIET_FGETS fgets 26 #endif 27 28 #if !defined(_WINDOWS) 29 static void 30 echoOff(int fd) 31 { 32 if (isatty(fd)) { 33 struct termios tio; 34 tcgetattr(fd, &tio); 35 tio.c_lflag &= ~ECHO; 36 tcsetattr(fd, TCSAFLUSH, &tio); 37 } 38 } 39 40 static void 41 echoOn(int fd) 42 { 43 if (isatty(fd)) { 44 struct termios tio; 45 tcgetattr(fd, &tio); 46 tio.c_lflag |= ECHO; 47 tcsetattr(fd, TCSAFLUSH, &tio); 48 } 49 } 50 #endif 51 52 char * 53 SEC_GetPassword(FILE *input, FILE *output, char *prompt, 54 PRBool (*ok)(char *)) 55 { 56 #if defined(_WINDOWS) 57 int isTTY = (input == stdin); 58 #define echoOn(x) 59 #define echoOff(x) 60 #else 61 int infd = fileno(input); 62 int isTTY = isatty(infd); 63 #endif 64 char phrase[500] = { '\0' }; /* ensure EOF doesn't return junk */ 65 66 for (;;) { 67 /* Prompt for password */ 68 if (isTTY) { 69 fprintf(output, "%s", prompt); 70 fflush(output); 71 echoOff(infd); 72 } 73 74 if (QUIET_FGETS(phrase, sizeof(phrase), input) == NULL) { 75 return NULL; 76 } 77 78 if (isTTY) { 79 fprintf(output, "\n"); 80 echoOn(infd); 81 } 82 83 /* stomp on newline */ 84 phrase[PORT_Strlen(phrase) - 1] = 0; 85 86 /* Validate password */ 87 if (!(*ok)(phrase)) { 88 /* Not weird enough */ 89 if (!isTTY) 90 return NULL; 91 fprintf(output, "Password must be at least 8 characters long with one or more\n"); 92 fprintf(output, "non-alphabetic characters\n"); 93 continue; 94 } 95 return (char *)PORT_Strdup(phrase); 96 } 97 } 98 99 PRBool 100 SEC_CheckPassword(char *cp) 101 { 102 int len; 103 char *end; 104 105 len = PORT_Strlen(cp); 106 if (len < 8) { 107 return PR_FALSE; 108 } 109 end = cp + len; 110 while (cp < end) { 111 unsigned char ch = *cp++; 112 if (!((ch >= 'A') && (ch <= 'Z')) && 113 !((ch >= 'a') && (ch <= 'z'))) { 114 /* pass phrase has at least one non alphabetic in it */ 115 return PR_TRUE; 116 } 117 } 118 return PR_FALSE; 119 } 120 121 PRBool 122 SEC_BlindCheckPassword(char *cp) 123 { 124 if (cp != NULL) { 125 return PR_TRUE; 126 } 127 return PR_FALSE; 128 } 129 130 /* Get a password from the input terminal, without echoing */ 131 132 #if defined(_WINDOWS) 133 static char * 134 quiet_fgets(char *buf, int length, FILE *input) 135 { 136 int c; 137 char *end = buf; 138 139 /* fflush (input); */ 140 memset(buf, 0, length); 141 142 if (!isatty(fileno(input))) { 143 return fgets(buf, length, input); 144 } 145 146 while (1) { 147 c = getch(); /* getch gets a character from the console */ 148 149 if (c == '\b') { 150 if (end > buf) 151 end--; 152 } 153 154 else if (--length > 0) 155 *end++ = c; 156 157 if (!c || c == '\n' || c == '\r') 158 break; 159 } 160 161 return buf; 162 } 163 #endif