+++ /dev/null
-/*\r
- * wincons.c - various interactive-prompt routines shared between\r
- * the Windows console PuTTY tools\r
- */\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <stdarg.h>\r
-\r
-#include "putty.h"\r
-#include "storage.h"\r
-#include "ssh.h"\r
-\r
-int console_batch_mode = FALSE;\r
-\r
-static void *console_logctx = NULL;\r
-\r
-/*\r
- * Clean up and exit.\r
- */\r
-void cleanup_exit(int code)\r
-{\r
- /*\r
- * Clean up.\r
- */\r
- sk_cleanup();\r
-\r
- random_save_seed();\r
-#ifdef MSCRYPTOAPI\r
- crypto_wrapup();\r
-#endif\r
-\r
- exit(code);\r
-}\r
-\r
-void set_busy_status(void *frontend, int status)\r
-{\r
-}\r
-\r
-void notify_remote_exit(void *frontend)\r
-{\r
-}\r
-\r
-void timer_change_notify(long next)\r
-{\r
-}\r
-\r
-int verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,\r
- char *keystr, char *fingerprint,\r
- void (*callback)(void *ctx, int result), void *ctx)\r
-{\r
- int ret;\r
- HANDLE hin;\r
- DWORD savemode, i;\r
-\r
- static const char absentmsg_batch[] =\r
- "The server's host key is not cached in the registry. You\n"\r
- "have no guarantee that the server is the computer you\n"\r
- "think it is.\n"\r
- "The server's %s key fingerprint is:\n"\r
- "%s\n"\r
- "Connection abandoned.\n";\r
- static const char absentmsg[] =\r
- "The server's host key is not cached in the registry. You\n"\r
- "have no guarantee that the server is the computer you\n"\r
- "think it is.\n"\r
- "The server's %s key fingerprint is:\n"\r
- "%s\n"\r
- "If you trust this host, enter \"y\" to add the key to\n"\r
- "PuTTY's cache and carry on connecting.\n"\r
- "If you want to carry on connecting just once, without\n"\r
- "adding the key to the cache, enter \"n\".\n"\r
- "If you do not trust this host, press Return to abandon the\n"\r
- "connection.\n"\r
- "Store key in cache? (y/n) ";\r
-\r
- static const char wrongmsg_batch[] =\r
- "WARNING - POTENTIAL SECURITY BREACH!\n"\r
- "The server's host key does not match the one PuTTY has\n"\r
- "cached in the registry. This means that either the\n"\r
- "server administrator has changed the host key, or you\n"\r
- "have actually connected to another computer pretending\n"\r
- "to be the server.\n"\r
- "The new %s key fingerprint is:\n"\r
- "%s\n"\r
- "Connection abandoned.\n";\r
- static const char wrongmsg[] =\r
- "WARNING - POTENTIAL SECURITY BREACH!\n"\r
- "The server's host key does not match the one PuTTY has\n"\r
- "cached in the registry. This means that either the\n"\r
- "server administrator has changed the host key, or you\n"\r
- "have actually connected to another computer pretending\n"\r
- "to be the server.\n"\r
- "The new %s key fingerprint is:\n"\r
- "%s\n"\r
- "If you were expecting this change and trust the new key,\n"\r
- "enter \"y\" to update PuTTY's cache and continue connecting.\n"\r
- "If you want to carry on connecting but without updating\n"\r
- "the cache, enter \"n\".\n"\r
- "If you want to abandon the connection completely, press\n"\r
- "Return to cancel. Pressing Return is the ONLY guaranteed\n"\r
- "safe choice.\n"\r
- "Update cached key? (y/n, Return cancels connection) ";\r
-\r
- static const char abandoned[] = "Connection abandoned.\n";\r
-\r
- char line[32];\r
-\r
- /*\r
- * Verify the key against the registry.\r
- */\r
- ret = verify_host_key(host, port, keytype, keystr);\r
-\r
- if (ret == 0) /* success - key matched OK */\r
- return 1;\r
-\r
- if (ret == 2) { /* key was different */\r
- if (console_batch_mode) {\r
- fprintf(stderr, wrongmsg_batch, keytype, fingerprint);\r
- return 0;\r
- }\r
- fprintf(stderr, wrongmsg, keytype, fingerprint);\r
- fflush(stderr);\r
- }\r
- if (ret == 1) { /* key was absent */\r
- if (console_batch_mode) {\r
- fprintf(stderr, absentmsg_batch, keytype, fingerprint);\r
- return 0;\r
- }\r
- fprintf(stderr, absentmsg, keytype, fingerprint);\r
- fflush(stderr);\r
- }\r
-\r
- hin = GetStdHandle(STD_INPUT_HANDLE);\r
- GetConsoleMode(hin, &savemode);\r
- SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT |\r
- ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT));\r
- ReadFile(hin, line, sizeof(line) - 1, &i, NULL);\r
- SetConsoleMode(hin, savemode);\r
-\r
- if (line[0] != '\0' && line[0] != '\r' && line[0] != '\n') {\r
- if (line[0] == 'y' || line[0] == 'Y')\r
- store_host_key(host, port, keytype, keystr);\r
- return 1;\r
- } else {\r
- fprintf(stderr, abandoned);\r
- return 0;\r
- }\r
-}\r
-\r
-void update_specials_menu(void *frontend)\r
-{\r
-}\r
-\r
-/*\r
- * Ask whether the selected algorithm is acceptable (since it was\r
- * below the configured 'warn' threshold).\r
- */\r
-int askalg(void *frontend, const char *algtype, const char *algname,\r
- void (*callback)(void *ctx, int result), void *ctx)\r
-{\r
- HANDLE hin;\r
- DWORD savemode, i;\r
-\r
- static const char msg[] =\r
- "The first %s supported by the server is\n"\r
- "%s, which is below the configured warning threshold.\n"\r
- "Continue with connection? (y/n) ";\r
- static const char msg_batch[] =\r
- "The first %s supported by the server is\n"\r
- "%s, which is below the configured warning threshold.\n"\r
- "Connection abandoned.\n";\r
- static const char abandoned[] = "Connection abandoned.\n";\r
-\r
- char line[32];\r
-\r
- if (console_batch_mode) {\r
- fprintf(stderr, msg_batch, algtype, algname);\r
- return 0;\r
- }\r
-\r
- fprintf(stderr, msg, algtype, algname);\r
- fflush(stderr);\r
-\r
- hin = GetStdHandle(STD_INPUT_HANDLE);\r
- GetConsoleMode(hin, &savemode);\r
- SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT |\r
- ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT));\r
- ReadFile(hin, line, sizeof(line) - 1, &i, NULL);\r
- SetConsoleMode(hin, savemode);\r
-\r
- if (line[0] == 'y' || line[0] == 'Y') {\r
- return 1;\r
- } else {\r
- fprintf(stderr, abandoned);\r
- return 0;\r
- }\r
-}\r
-\r
-/*\r
- * Ask whether to wipe a session log file before writing to it.\r
- * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).\r
- */\r
-int askappend(void *frontend, Filename filename,\r
- void (*callback)(void *ctx, int result), void *ctx)\r
-{\r
- HANDLE hin;\r
- DWORD savemode, i;\r
-\r
- static const char msgtemplate[] =\r
- "The session log file \"%.*s\" already exists.\n"\r
- "You can overwrite it with a new session log,\n"\r
- "append your session log to the end of it,\n"\r
- "or disable session logging for this session.\n"\r
- "Enter \"y\" to wipe the file, \"n\" to append to it,\n"\r
- "or just press Return to disable logging.\n"\r
- "Wipe the log file? (y/n, Return cancels logging) ";\r
-\r
- static const char msgtemplate_batch[] =\r
- "The session log file \"%.*s\" already exists.\n"\r
- "Logging will not be enabled.\n";\r
-\r
- char line[32];\r
-\r
- if (console_batch_mode) {\r
- fprintf(stderr, msgtemplate_batch, FILENAME_MAX, filename.path);\r
- fflush(stderr);\r
- return 0;\r
- }\r
- fprintf(stderr, msgtemplate, FILENAME_MAX, filename.path);\r
- fflush(stderr);\r
-\r
- hin = GetStdHandle(STD_INPUT_HANDLE);\r
- GetConsoleMode(hin, &savemode);\r
- SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT |\r
- ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT));\r
- ReadFile(hin, line, sizeof(line) - 1, &i, NULL);\r
- SetConsoleMode(hin, savemode);\r
-\r
- if (line[0] == 'y' || line[0] == 'Y')\r
- return 2;\r
- else if (line[0] == 'n' || line[0] == 'N')\r
- return 1;\r
- else\r
- return 0;\r
-}\r
-\r
-/*\r
- * Warn about the obsolescent key file format.\r
- * \r
- * Uniquely among these functions, this one does _not_ expect a\r
- * frontend handle. This means that if PuTTY is ported to a\r
- * platform which requires frontend handles, this function will be\r
- * an anomaly. Fortunately, the problem it addresses will not have\r
- * been present on that platform, so it can plausibly be\r
- * implemented as an empty function.\r
- */\r
-void old_keyfile_warning(void)\r
-{\r
- static const char message[] =\r
- "You are loading an SSH-2 private key which has an\n"\r
- "old version of the file format. This means your key\n"\r
- "file is not fully tamperproof. Future versions of\n"\r
- "PuTTY may stop supporting this private key format,\n"\r
- "so we recommend you convert your key to the new\n"\r
- "format.\n"\r
- "\n"\r
- "Once the key is loaded into PuTTYgen, you can perform\n"\r
- "this conversion simply by saving it again.\n";\r
-\r
- fputs(message, stderr);\r
-}\r
-\r
-/*\r
- * Display the fingerprints of the PGP Master Keys to the user.\r
- */\r
-void pgp_fingerprints(void)\r
-{\r
- fputs("These are the fingerprints of the PuTTY PGP Master Keys. They can\n"\r
- "be used to establish a trust path from this executable to another\n"\r
- "one. See the manual for more information.\n"\r
- "(Note: these fingerprints have nothing to do with SSH!)\n"\r
- "\n"\r
- "PuTTY Master Key (RSA), 1024-bit:\n"\r
- " " PGP_RSA_MASTER_KEY_FP "\n"\r
- "PuTTY Master Key (DSA), 1024-bit:\n"\r
- " " PGP_DSA_MASTER_KEY_FP "\n", stdout);\r
-}\r
-\r
-void console_provide_logctx(void *logctx)\r
-{\r
- console_logctx = logctx;\r
-}\r
-\r
-void logevent(void *frontend, const char *string)\r
-{\r
- log_eventlog(console_logctx, string);\r
-}\r
-\r
-static void console_data_untrusted(HANDLE hout, const char *data, int len)\r
-{\r
- DWORD dummy;\r
- /* FIXME: control-character filtering */\r
- WriteFile(hout, data, len, &dummy, NULL);\r
-}\r
-\r
-int console_get_userpass_input(prompts_t *p, unsigned char *in, int inlen)\r
-{\r
- HANDLE hin, hout;\r
- size_t curr_prompt;\r
-\r
- /*\r
- * Zero all the results, in case we abort half-way through.\r
- */\r
- {\r
- int i;\r
- for (i = 0; i < (int)p->n_prompts; i++)\r
- memset(p->prompts[i]->result, 0, p->prompts[i]->result_len);\r
- }\r
-\r
- /*\r
- * The prompts_t might contain a message to be displayed but no\r
- * actual prompt. More usually, though, it will contain\r
- * questions that the user needs to answer, in which case we\r
- * need to ensure that we're able to get the answers.\r
- */\r
- if (p->n_prompts) {\r
- if (console_batch_mode)\r
- return 0;\r
- hin = GetStdHandle(STD_INPUT_HANDLE);\r
- if (hin == INVALID_HANDLE_VALUE) {\r
- fprintf(stderr, "Cannot get standard input handle\n");\r
- cleanup_exit(1);\r
- }\r
- }\r
-\r
- /*\r
- * And if we have anything to print, we need standard output.\r
- */\r
- if ((p->name_reqd && p->name) || p->instruction || p->n_prompts) {\r
- hout = GetStdHandle(STD_OUTPUT_HANDLE);\r
- if (hout == INVALID_HANDLE_VALUE) {\r
- fprintf(stderr, "Cannot get standard output handle\n");\r
- cleanup_exit(1);\r
- }\r
- }\r
-\r
- /*\r
- * Preamble.\r
- */\r
- /* We only print the `name' caption if we have to... */\r
- if (p->name_reqd && p->name) {\r
- size_t l = strlen(p->name);\r
- console_data_untrusted(hout, p->name, l);\r
- if (p->name[l-1] != '\n')\r
- console_data_untrusted(hout, "\n", 1);\r
- }\r
- /* ...but we always print any `instruction'. */\r
- if (p->instruction) {\r
- size_t l = strlen(p->instruction);\r
- console_data_untrusted(hout, p->instruction, l);\r
- if (p->instruction[l-1] != '\n')\r
- console_data_untrusted(hout, "\n", 1);\r
- }\r
-\r
- for (curr_prompt = 0; curr_prompt < p->n_prompts; curr_prompt++) {\r
-\r
- DWORD savemode, newmode, i = 0;\r
- prompt_t *pr = p->prompts[curr_prompt];\r
- BOOL r;\r
-\r
- GetConsoleMode(hin, &savemode);\r
- newmode = savemode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT;\r
- if (!pr->echo)\r
- newmode &= ~ENABLE_ECHO_INPUT;\r
- else\r
- newmode |= ENABLE_ECHO_INPUT;\r
- SetConsoleMode(hin, newmode);\r
-\r
- console_data_untrusted(hout, pr->prompt, strlen(pr->prompt));\r
-\r
- r = ReadFile(hin, pr->result, pr->result_len - 1, &i, NULL);\r
-\r
- SetConsoleMode(hin, savemode);\r
-\r
- if ((int) i > pr->result_len)\r
- i = pr->result_len - 1;\r
- else\r
- i = i - 2;\r
- pr->result[i] = '\0';\r
-\r
- if (!pr->echo) {\r
- DWORD dummy;\r
- WriteFile(hout, "\r\n", 2, &dummy, NULL);\r
- }\r
-\r
- }\r
-\r
- return 1; /* success */\r
-\r
-}\r
-\r
-void frontend_keypress(void *handle)\r
-{\r
- /*\r
- * This is nothing but a stub, in console code.\r
- */\r
- return;\r
-}\r