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