X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/449925a68090c785f7399b269f0f846e98f32961..0622ea7168aa265db70be885fbffb050f29f0205:/plink.c diff --git a/plink.c b/plink.c index 1b742cec..047414ad 100644 --- a/plink.c +++ b/plink.c @@ -42,126 +42,6 @@ void connection_fatal(char *p, ...) static char *password = NULL; -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 want to carry on connecting just once, without\n" - "adding the key to the cache, enter \"n\".\n" - "If you do not trust this host, press Return to abandon the\n" - "connection.\n" - "Store key in cache? (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; - - if (ret == 2) { /* key was different */ - fprintf(stderr, wrongmsg, fingerprint); - fflush(stderr); - } - if (ret == 1) { /* key was absent */ - fprintf(stderr, absentmsg, fingerprint); - fflush(stderr); - } - - 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 (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); - } -} - -/* - * Ask whether the selected cipher is acceptable (since it was - * below the configured 'warn' threshold). - * cs: 0 = both ways, 1 = client->server, 2 = server->client - */ -void askcipher(char *ciphername, int cs) -{ - HANDLE hin; - DWORD savemode, i; - - static const char msg[] = - "The first %scipher supported by the server is\n" - "%s, which is below the configured warning threshold.\n" - "Continue with connection? (y/n) "; - static const char abandoned[] = "Connection abandoned.\n"; - - char line[32]; - - fprintf(stderr, msg, - (cs == 0) ? "" : - (cs == 1) ? "client-to-server " : - "server-to-client ", - ciphername); - fflush(stderr); - - 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 (line[0] == 'y' || line[0] == 'Y') { - return; - } else { - fprintf(stderr, abandoned); - exit(0); - } -} - HANDLE inhandle, outhandle, errhandle; DWORD orig_console_mode; @@ -188,56 +68,6 @@ void ldisc_update(int echo, int edit) SetConsoleMode(inhandle, mode); } -static int get_line(const char *prompt, char *str, int maxlen, int is_pw) -{ - HANDLE hin, hout; - DWORD savemode, newmode, i; - - if (is_pw && password) { - static int tried_once = 0; - - if (tried_once) { - return 0; - } else { - strncpy(str, password, maxlen); - str[maxlen - 1] = '\0'; - tried_once = 1; - return 1; - } - } - - hin = GetStdHandle(STD_INPUT_HANDLE); - hout = GetStdHandle(STD_OUTPUT_HANDLE); - if (hin == INVALID_HANDLE_VALUE || hout == INVALID_HANDLE_VALUE) { - fprintf(stderr, "Cannot get standard input/output handles"); - return 0; - } - - GetConsoleMode(hin, &savemode); - newmode = savemode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT; - if (is_pw) - newmode &= ~ENABLE_ECHO_INPUT; - else - newmode |= ENABLE_ECHO_INPUT; - SetConsoleMode(hin, newmode); - - WriteFile(hout, prompt, strlen(prompt), &i, NULL); - ReadFile(hin, str, maxlen - 1, &i, NULL); - - SetConsoleMode(hin, savemode); - - if ((int) i > maxlen) - i = maxlen - 1; - else - i = i - 2; - str[i] = '\0'; - - if (is_pw) - WriteFile(hout, "\r\n", 2, &i, NULL); - - return 1; -} - struct input_data { DWORD len; char buffer[4096]; @@ -346,6 +176,10 @@ static void usage(void) printf(" -P port connect to specified port\n"); printf(" -pw passw login with specified password\n"); printf(" -m file read remote command(s) from file\n"); + printf(" -L listen-port:host:port Forward local port to " + "remote address\n"); + printf(" -R listen-port:host:port Forward remote port to" + " local address\n"); exit(1); } @@ -383,8 +217,10 @@ int main(int argc, char **argv) SOCKET *sklist; int skcount, sksize; int connopen; + int exitcode; + char extra_portfwd[sizeof(cfg.portfwd)]; - ssh_get_line = get_line; + ssh_get_line = console_get_line; sklist = NULL; skcount = sksize = 0; @@ -428,19 +264,42 @@ int main(int argc, char **argv) } else if (!strcmp(p, "-telnet")) { default_protocol = cfg.protocol = PROT_TELNET; default_port = cfg.port = 23; + } else if (!strcmp(p, "-rlogin")) { + default_protocol = cfg.protocol = PROT_RLOGIN; + default_port = cfg.port = 513; } else if (!strcmp(p, "-raw")) { default_protocol = cfg.protocol = PROT_RAW; + } else if (!strcmp(p, "-batch")) { + console_batch_mode = TRUE; } else if (!strcmp(p, "-v")) { flags |= FLAG_VERBOSE; } else if (!strcmp(p, "-log")) { logfile = "putty.log"; } else if (!strcmp(p, "-pw") && argc > 1) { - --argc, password = *++argv; + --argc, console_password = *++argv; } else if (!strcmp(p, "-l") && argc > 1) { char *username; --argc, username = *++argv; strncpy(cfg.username, username, sizeof(cfg.username)); cfg.username[sizeof(cfg.username) - 1] = '\0'; + } else if ((!strcmp(p, "-L") || !strcmp(p, "-R")) && argc > 1) { + char *fwd, *ptr, *q; + int i=0; + --argc, fwd = *++argv; + ptr = extra_portfwd; + /* if multiple forwards, find end of list */ + if (ptr[0]=='R' || ptr[0]=='L') { + for (i = 0; i < sizeof(extra_portfwd) - 2; i++) + if (ptr[i]=='\000' && ptr[i+1]=='\000') + break; + ptr = ptr + i + 1; /* point to next forward slot */ + } + ptr[0] = p[1]; /* insert a 'L' or 'R' at the start */ + strncpy(ptr+1, fwd, sizeof(extra_portfwd) - i); + q = strchr(ptr, ':'); + if (q) *q = '\t'; /* replace first : with \t */ + ptr[strlen(ptr)+1] = '\000'; /* append two '\000' */ + extra_portfwd[sizeof(extra_portfwd) - 1] = '\0'; } else if (!strcmp(p, "-m") && argc > 1) { char *filename, *command; int cmdlen, cmdsize; @@ -640,6 +499,30 @@ int main(int argc, char **argv) } /* + * Add extra port forwardings (accumulated on command line) to + * cfg. + */ + { + int i; + char *p; + p = extra_portfwd; + i = 0; + while (cfg.portfwd[i]) + i += strlen(cfg.portfwd+i) + 1; + while (*p) { + if (strlen(p)+2 > sizeof(cfg.portfwd)-i) { + fprintf(stderr, "Internal fault: not enough space for all" + " port forwardings\n"); + break; + } + strncpy(cfg.portfwd+i, p, sizeof(cfg.portfwd)-i-1); + i += strlen(cfg.portfwd+i) + 1; + cfg.portfwd[i] = '\0'; + p += strlen(p)+1; + } + } + + /* * Select port. */ if (portnumber != -1) @@ -669,8 +552,11 @@ int main(int argc, char **argv) { char *error; char *realhost; + /* nodelay is only useful if stdin is a character device (console) */ + int nodelay = cfg.tcp_nodelay && + (GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR); - error = back->init(cfg.host, cfg.port, &realhost); + error = back->init(cfg.host, cfg.port, &realhost, nodelay); if (error) { fprintf(stderr, "Unable to open connection:\n%s", error); return 1; @@ -857,5 +743,10 @@ int main(int argc, char **argv) break; /* we closed the connection */ } WSACleanup(); - return 0; + exitcode = back->exitcode(); + if (exitcode < 0) { + fprintf(stderr, "Remote process exit code unavailable\n"); + exitcode = 1; /* this is an error condition */ + } + return exitcode; }