2 * console.c: various interactive-prompt routines shared between
3 * the console PuTTY tools
16 int console_batch_mode
= FALSE
;
18 void verify_ssh_host_key(char *host
, int port
, char *keytype
,
19 char *keystr
, char *fingerprint
)
25 static const char absentmsg_batch
[] =
26 "The server's host key is not cached in the registry. You\n"
27 "have no guarantee that the server is the computer you\n"
29 "The server's key fingerprint is:\n"
31 "Connection abandoned.\n";
32 static const char absentmsg
[] =
33 "The server's host key is not cached in the registry. You\n"
34 "have no guarantee that the server is the computer you\n"
36 "The server's key fingerprint is:\n"
38 "If you trust this host, enter \"y\" to add the key to\n"
39 "PuTTY's cache and carry on connecting.\n"
40 "If you want to carry on connecting just once, without\n"
41 "adding the key to the cache, enter \"n\".\n"
42 "If you do not trust this host, press Return to abandon the\n"
44 "Store key in cache? (y/n) ";
46 static const char wrongmsg_batch
[] =
47 "WARNING - POTENTIAL SECURITY BREACH!\n"
48 "The server's host key does not match the one PuTTY has\n"
49 "cached in the registry. This means that either the\n"
50 "server administrator has changed the host key, or you\n"
51 "have actually connected to another computer pretending\n"
53 "The new key fingerprint is:\n"
55 "Connection abandoned.\n";
56 static const char wrongmsg
[] =
57 "WARNING - POTENTIAL SECURITY BREACH!\n"
58 "The server's host key does not match the one PuTTY has\n"
59 "cached in the registry. This means that either the\n"
60 "server administrator has changed the host key, or you\n"
61 "have actually connected to another computer pretending\n"
63 "The new key fingerprint is:\n"
65 "If you were expecting this change and trust the new key,\n"
66 "enter \"y\" to update PuTTY's cache and continue connecting.\n"
67 "If you want to carry on connecting but without updating\n"
68 "the cache, enter \"n\".\n"
69 "If you want to abandon the connection completely, press\n"
70 "Return to cancel. Pressing Return is the ONLY guaranteed\n"
72 "Update cached key? (y/n, Return cancels connection) ";
74 static const char abandoned
[] = "Connection abandoned.\n";
79 * Verify the key against the registry.
81 ret
= verify_host_key(host
, port
, keytype
, keystr
);
83 if (ret
== 0) /* success - key matched OK */
86 if (ret
== 2) { /* key was different */
87 if (console_batch_mode
) {
88 fprintf(stderr
, wrongmsg_batch
, fingerprint
);
91 fprintf(stderr
, wrongmsg
, fingerprint
);
94 if (ret
== 1) { /* key was absent */
95 if (console_batch_mode
) {
96 fprintf(stderr
, absentmsg_batch
, fingerprint
);
99 fprintf(stderr
, absentmsg
, fingerprint
);
103 hin
= GetStdHandle(STD_INPUT_HANDLE
);
104 GetConsoleMode(hin
, &savemode
);
105 SetConsoleMode(hin
, (savemode
| ENABLE_ECHO_INPUT
|
106 ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
));
107 ReadFile(hin
, line
, sizeof(line
) - 1, &i
, NULL
);
108 SetConsoleMode(hin
, savemode
);
110 if (line
[0] != '\0' && line
[0] != '\r' && line
[0] != '\n') {
111 if (line
[0] == 'y' || line
[0] == 'Y')
112 store_host_key(host
, port
, keytype
, keystr
);
114 fprintf(stderr
, abandoned
);
120 * Ask whether the selected cipher is acceptable (since it was
121 * below the configured 'warn' threshold).
122 * cs: 0 = both ways, 1 = client->server, 2 = server->client
124 void askcipher(char *ciphername
, int cs
)
129 static const char msg
[] =
130 "The first %scipher supported by the server is\n"
131 "%s, which is below the configured warning threshold.\n"
132 "Continue with connection? (y/n) ";
133 static const char msg_batch
[] =
134 "The first %scipher supported by the server is\n"
135 "%s, which is below the configured warning threshold.\n"
136 "Connection abandoned.\n";
137 static const char abandoned
[] = "Connection abandoned.\n";
141 if (console_batch_mode
) {
142 fprintf(stderr
, msg_batch
,
144 (cs
== 1) ?
"client-to-server " : "server-to-client ",
151 (cs
== 1) ?
"client-to-server " : "server-to-client ",
155 hin
= GetStdHandle(STD_INPUT_HANDLE
);
156 GetConsoleMode(hin
, &savemode
);
157 SetConsoleMode(hin
, (savemode
| ENABLE_ECHO_INPUT
|
158 ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
));
159 ReadFile(hin
, line
, sizeof(line
) - 1, &i
, NULL
);
160 SetConsoleMode(hin
, savemode
);
162 if (line
[0] == 'y' || line
[0] == 'Y') {
165 fprintf(stderr
, abandoned
);
171 * Ask whether to wipe a session log file before writing to it.
172 * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
174 int askappend(char *filename
)
179 static const char msgtemplate
[] =
180 "The session log file \"%.*s\" already exists.\n"
181 "You can overwrite it with a new session log,\n"
182 "append your session log to the end of it,\n"
183 "or disable session logging for this session.\n"
184 "Enter \"y\" to wipe the file, \"n\" to append to it,\n"
185 "or just press Return to disable logging.\n"
186 "Wipe the log file? (y/n, Return cancels logging) ";
188 static const char msgtemplate_batch
[] =
189 "The session log file \"%.*s\" already exists.\n"
190 "Logging will not be enabled.\n";
194 if (console_batch_mode
) {
195 fprintf(stderr
, msgtemplate_batch
, FILENAME_MAX
, filename
);
199 fprintf(stderr
, msgtemplate
, FILENAME_MAX
, filename
);
202 hin
= GetStdHandle(STD_INPUT_HANDLE
);
203 GetConsoleMode(hin
, &savemode
);
204 SetConsoleMode(hin
, (savemode
| ENABLE_ECHO_INPUT
|
205 ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
));
206 ReadFile(hin
, line
, sizeof(line
) - 1, &i
, NULL
);
207 SetConsoleMode(hin
, savemode
);
209 if (line
[0] == 'y' || line
[0] == 'Y')
211 else if (line
[0] == 'n' || line
[0] == 'N')
218 * Warn about the obsolescent key file format.
220 void old_keyfile_warning(void)
222 static const char message
[] =
223 "You are loading an SSH 2 private key which has an\n"
224 "old version of the file format. This means your key\n"
225 "file is not fully tamperproof. Future versions of\n"
226 "PuTTY may stop supporting this private key format,\n"
227 "so we recommend you convert your key to the new\n"
230 "Once the key is loaded into PuTTYgen, you can perform\n"
231 "this conversion simply by saving it again.\n";
233 fputs(message
, stderr
);
236 void logevent(char *string
)
240 char *console_password
= NULL
;
242 int console_get_line(const char *prompt
, char *str
,
243 int maxlen
, int is_pw
)
246 DWORD savemode
, newmode
, i
;
248 if (is_pw
&& console_password
) {
249 static int tried_once
= 0;
254 strncpy(str
, console_password
, maxlen
);
255 str
[maxlen
- 1] = '\0';
261 if (console_batch_mode
) {
265 hin
= GetStdHandle(STD_INPUT_HANDLE
);
266 hout
= GetStdHandle(STD_OUTPUT_HANDLE
);
267 if (hin
== INVALID_HANDLE_VALUE
|| hout
== INVALID_HANDLE_VALUE
) {
268 fprintf(stderr
, "Cannot get standard input/output handles\n");
272 GetConsoleMode(hin
, &savemode
);
273 newmode
= savemode
| ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
;
275 newmode
&= ~ENABLE_ECHO_INPUT
;
277 newmode
|= ENABLE_ECHO_INPUT
;
278 SetConsoleMode(hin
, newmode
);
280 WriteFile(hout
, prompt
, strlen(prompt
), &i
, NULL
);
281 ReadFile(hin
, str
, maxlen
- 1, &i
, NULL
);
283 SetConsoleMode(hin
, savemode
);
285 if ((int) i
> maxlen
)
292 WriteFile(hout
, "\r\n", 2, &i
, NULL
);