X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/8cb9c947887dc7c26e7d02ccdb59e092c88e46a2..fe50e8140a2dbb3ba357a0ab777f34e07d568c23:/plink.c diff --git a/plink.c b/plink.c index 6ac5e0ac..26a17292 100644 --- a/plink.c +++ b/plink.c @@ -11,6 +11,8 @@ #define PUTTY_DO_GLOBALS /* actually _define_ globals */ #include "putty.h" +#include "winstuff.h" +#include "storage.h" void fatalbox (char *p, ...) { va_list ap; @@ -35,13 +37,88 @@ void connection_fatal (char *p, ...) { static char *password = NULL; -/* - * Stubs for linking with other modules. - */ -void write_clip (void *data, int len) { } -void term_deselect(void) { } +void logevent(char *string) { } + +void verify_ssh_host_key(char *host, int port, char *keytype, + char *keystr, char *fingerprint) { + int ret; + HANDLE hin; + DWORD savemode, i; + + static const char absentmsg[] = + "The server's host key is not cached in the registry. You\n" + "have no guarantee that the server is the computer you\n" + "think it is.\n" + "The server's key fingerprint is:\n" + "%s\n" + "If you trust this host, enter \"y\" to add the key to\n" + "PuTTY's cache and carry on connecting.\n" + "If you do not trust this host, enter \"n\" to abandon the\n" + "connection.\n" + "Continue connecting? (y/n) "; + + static const char wrongmsg[] = + "WARNING - POTENTIAL SECURITY BREACH!\n" + "The server's host key does not match the one PuTTY has\n" + "cached in the registry. This means that either the\n" + "server administrator has changed the host key, or you\n" + "have actually connected to another computer pretending\n" + "to be the server.\n" + "The new key fingerprint is:\n" + "%s\n" + "If you were expecting this change and trust the new key,\n" + "enter \"y\" to update PuTTY's cache and continue connecting.\n" + "If you want to carry on connecting but without updating\n" + "the cache, enter \"n\".\n" + "If you want to abandon the connection completely, press\n" + "Return to cancel. Pressing Return is the ONLY guaranteed\n" + "safe choice.\n" + "Update cached key? (y/n, Return cancels connection) "; + + static const char abandoned[] = "Connection abandoned.\n"; + + char line[32]; + + /* + * Verify the key against the registry. + */ + ret = verify_host_key(host, port, keytype, keystr); + + if (ret == 0) /* success - key matched OK */ + return; -HANDLE outhandle; + if (ret == 2) /* key was different */ + fprintf(stderr, wrongmsg, fingerprint); + if (ret == 1) /* key was absent */ + fprintf(stderr, absentmsg, fingerprint); + + hin = GetStdHandle(STD_INPUT_HANDLE); + GetConsoleMode(hin, &savemode); + SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT | + ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)); + ReadFile(hin, line, sizeof(line)-1, &i, NULL); + SetConsoleMode(hin, savemode); + + if (ret == 2) { /* key was different */ + if (line[0] != '\0' && line[0] != '\r' && line[0] != '\n') { + if (line[0] == 'y' || line[0] == 'Y') + store_host_key(host, port, keytype, keystr); + } else { + fprintf(stderr, abandoned); + exit(0); + } + } + if (ret == 1) { /* key was absent */ + if (line[0] == 'y' || line[0] == 'Y') + store_host_key(host, port, keytype, keystr); + else { + fprintf(stderr, abandoned); + exit(0); + } + } +} + +HANDLE outhandle, errhandle; DWORD orig_console_mode; void begin_session(void) { @@ -51,17 +128,17 @@ void begin_session(void) { SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), orig_console_mode); } -void term_out(void) -{ - int reap; +void from_backend(int is_stderr, char *data, int len) { + int pos; DWORD ret; - reap = 0; - while (reap < inbuf_head) { - if (!WriteFile(outhandle, inbuf+reap, inbuf_head-reap, &ret, NULL)) + HANDLE h = (is_stderr ? errhandle : outhandle); + + pos = 0; + while (pos < len) { + if (!WriteFile(h, data+pos, len-pos, &ret, NULL)) return; /* give up in panic */ - reap += ret; + pos += ret; } - inbuf_head = 0; } struct input_data { @@ -112,7 +189,7 @@ static int get_password(const char *prompt, char *str, int maxlen) return 1; } -int WINAPI stdin_read_thread(void *param) { +static DWORD WINAPI stdin_read_thread(void *param) { struct input_data *idata = (struct input_data *)param; HANDLE inhandle; @@ -162,7 +239,7 @@ int main(int argc, char **argv) { /* * Process the command line. */ - do_defaults(NULL); + do_defaults(NULL, &cfg); default_protocol = cfg.protocol; default_port = cfg.port; { @@ -270,7 +347,7 @@ int main(int argc, char **argv) { /* * One string. */ - do_defaults (p); + do_defaults (p, &cfg); if (cfg.host[0] == '\0') { /* No settings for this host; use defaults */ strncpy(cfg.host, p, sizeof(cfg.host)-1); @@ -373,6 +450,7 @@ int main(int argc, char **argv) { GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &orig_console_mode); SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT); outhandle = GetStdHandle(STD_OUTPUT_HANDLE); + errhandle = GetStdHandle(STD_ERROR_HANDLE); /* * Now we must send the back end oodles of stuff. @@ -427,7 +505,6 @@ int main(int argc, char **argv) { break; } } - term_out(); } else if (n == 1) { if (idata.len > 0) { back->send(idata.buffer, idata.len); @@ -435,6 +512,8 @@ int main(int argc, char **argv) { back->special(TS_EOF); } } + if (back->socket() == INVALID_SOCKET) + break; /* we closed the connection */ } WSACleanup(); return 0;