X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=unix%2Fuxplink.c;h=2d4259b91abd5e80ae955c8f1047a38777f632f1;hb=3f29d939ee6d20789eff0fb779592f64fc4bf892;hp=ee5cef8aa30f0d50d37f5a99cdacb7f6ec5af679;hpb=5c4ce2fadf23bff6f38155df44b5d6040cf80d26;p=PuTTY.git diff --git a/unix/uxplink.c b/unix/uxplink.c index ee5cef8a..2d4259b9 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -25,11 +25,11 @@ #define MAX_STDIN_BACKLOG 4096 -void *logctx; +static void *logctx; static struct termios orig_termios; -void fatalbox(char *p, ...) +void fatalbox(const char *p, ...) { struct termios cf; va_list ap; @@ -46,7 +46,7 @@ void fatalbox(char *p, ...) } cleanup_exit(1); } -void modalfatalbox(char *p, ...) +void modalfatalbox(const char *p, ...) { struct termios cf; va_list ap; @@ -63,7 +63,7 @@ void modalfatalbox(char *p, ...) } cleanup_exit(1); } -void nonfatal(char *p, ...) +void nonfatal(const char *p, ...) { struct termios cf; va_list ap; @@ -74,12 +74,8 @@ void nonfatal(char *p, ...) va_end(ap); fputc('\n', stderr); postmsg(&cf); - if (logctx) { - log_free(logctx); - logctx = NULL; - } } -void connection_fatal(void *frontend, char *p, ...) +void connection_fatal(void *frontend, const char *p, ...) { struct termios cf; va_list ap; @@ -96,7 +92,7 @@ void connection_fatal(void *frontend, char *p, ...) } cleanup_exit(1); } -void cmdline_error(char *p, ...) +void cmdline_error(const char *p, ...) { struct termios cf; va_list ap; @@ -117,14 +113,12 @@ static void *backhandle; static Conf *conf; /* - * Default settings that are specific to pterm. + * Default settings that are specific to Unix plink. */ char *platform_default_s(const char *name) { if (!strcmp(name, "TermType")) return dupstr(getenv("TERM")); - if (!strcmp(name, "UserName")) - return get_username(); if (!strcmp(name, "SerialLine")) return dupstr("/dev/ttyS0"); return NULL; @@ -156,7 +150,7 @@ int term_ldisc(Terminal *term, int mode) { return FALSE; } -void ldisc_update(void *frontend, int echo, int edit) +void frontend_echoedit_update(void *frontend, int echo, int edit) { /* Update stdin read mode to reflect changes in line discipline. */ struct termios mode; @@ -182,8 +176,9 @@ void ldisc_update(void *frontend, int echo, int edit) mode.c_cc[VMIN] = 1; mode.c_cc[VTIME] = 0; /* FIXME: perhaps what we do with IXON/IXOFF should be an - * argument to ldisc_update(), to allow implementation of SSH-2 - * "xon-xoff" and Rlogin's equivalent? */ + * argument to frontend_echoedit_update(), to allow + * implementation of SSH-2 "xon-xoff" and Rlogin's + * equivalent? */ mode.c_iflag &= ~IXON; mode.c_iflag &= ~IXOFF; } @@ -208,7 +203,7 @@ static char *get_ttychar(struct termios *t, int index) cc_t c = t->c_cc[index]; #if defined(_POSIX_VDISABLE) if (c == _POSIX_VDISABLE) - return dupprintf(""); + return dupstr(""); #endif return dupprintf("^<%d>", c); } @@ -310,6 +305,9 @@ char *get_ttymode(void *frontend, const char *mode) #endif #if defined(XCASE) GET_BOOL("XCASE", XCASE, c_lflag, ); +#endif +#if defined(IUTF8) + GET_BOOL("IUTF8", IUTF8, c_iflag, ); #endif /* Configuration of ECHO */ #if defined(ECHOCTL) @@ -451,7 +449,7 @@ int from_backend_eof(void *frontend_handle) return FALSE; /* do not respond to incoming EOF with outgoing */ } -int get_userpass_input(prompts_t *p, unsigned char *in, int inlen) +int get_userpass_input(prompts_t *p, const unsigned char *in, int inlen) { int ret; ret = cmdline_get_passwd_input(p, in, inlen); @@ -538,15 +536,15 @@ void sigwinch(int signum) * In Plink our selects are synchronous, so these functions are * empty stubs. */ -int uxsel_input_add(int fd, int rwx) { return 0; } -void uxsel_input_remove(int id) { } +uxsel_id *uxsel_input_add(int fd, int rwx) { return NULL; } +void uxsel_input_remove(uxsel_id *id) { } /* * Short description of parameters. */ static void usage(void) { - printf("PuTTY Link: command-line connection utility\n"); + printf("Plink: command-line connection utility\n"); printf("%s\n", ver); printf("Usage: plink [options] [user@]host [command]\n"); printf(" (\"host\" can also be a PuTTY saved session name)\n"); @@ -560,6 +558,10 @@ static void usage(void) printf(" -P port connect to specified port\n"); printf(" -l user connect with specified username\n"); printf(" -batch disable all interactive prompts\n"); + printf(" -proxycmd command\n"); + printf(" use 'command' as local proxy\n"); + printf(" -sercfg configuration-string (e.g. 19200,8,n,1,X)\n"); + printf(" Specify the serial configuration (serial only)\n"); printf("The following options only apply to SSH connections:\n"); printf(" -pw passw login with specified password\n"); printf(" -D [listen-IP:]listen-port\n"); @@ -574,27 +576,39 @@ static void usage(void) printf(" -1 -2 force use of particular protocol version\n"); printf(" -4 -6 force use of IPv4 or IPv6\n"); printf(" -C enable compression\n"); - printf(" -i key private key file for authentication\n"); + printf(" -i key private key file for user authentication\n"); printf(" -noagent disable use of Pageant\n"); printf(" -agent enable use of Pageant\n"); + printf(" -hostkey aa:bb:cc:...\n"); + printf(" manually specify a host key (may be repeated)\n"); printf(" -m file read remote command(s) from file\n"); printf(" -s remote command is an SSH subsystem (SSH-2 only)\n"); printf(" -N don't start a shell/command (SSH-2 only)\n"); printf(" -nc host:port\n"); printf(" open tunnel in place of session (SSH-2 only)\n"); - printf(" -sercfg configuration-string (e.g. 19200,8,n,1,X)\n"); - printf(" Specify the serial configuration (serial only)\n"); + printf(" -sshlog file\n"); + printf(" -sshrawlog file\n"); + printf(" log protocol details to a file\n"); + printf(" -shareexists\n"); + printf(" test whether a connection-sharing upstream exists\n"); exit(1); } static void version(void) { - printf("plink: %s\n", ver); - exit(1); + char *buildinfo_text = buildinfo("\n"); + printf("plink: %s\n%s\n", ver, buildinfo_text); + sfree(buildinfo_text); + exit(0); } void frontend_net_error_pending(void) {} +const int share_can_be_downstream = TRUE; +const int share_can_be_upstream = TRUE; + +const int buildinfo_gtk_relevant = FALSE; + int main(int argc, char **argv) { int sending; @@ -607,6 +621,7 @@ int main(int argc, char **argv) int errors; int use_subsystem = 0; int got_host = FALSE; + int just_test_share_exists = FALSE; unsigned long now; struct winsize size; @@ -685,6 +700,12 @@ int main(int argc, char **argv) --argc; provide_xrm_string(*++argv); } + } else if (!strcmp(p, "-shareexists")) { + just_test_share_exists = TRUE; + } else if (!strcmp(p, "-fuzznet")) { + conf_set_int(conf, CONF_proxy_type, PROXY_FUZZ); + conf_set_str(conf, CONF_proxy_telnet_command, + "%host"); } else { fprintf(stderr, "plink: unknown option \"%s\"\n", p); errors = 1; @@ -706,8 +727,7 @@ int main(int argc, char **argv) q += 2; conf_set_int(conf, CONF_protocol, PROT_TELNET); p = q; - while (*p && *p != ':' && *p != '/') - p++; + p += host_strcspn(p, ":/"); c = *p; if (*p) *p++ = '\0'; @@ -845,10 +865,21 @@ int main(int argc, char **argv) } } - /* - * Trim off a colon suffix if it's there. - */ - host[strcspn(host, ":")] = '\0'; + /* + * Trim a colon suffix off the hostname if it's there. In + * order to protect unbracketed IPv6 address literals + * against this treatment, we do not do this if there's + * _more_ than one colon. + */ + { + char *c = host_strchr(host, ':'); + + if (c) { + char *d = host_strchr(c+1, ':'); + if (!d) + *c = '\0'; + } + } /* * Remove any remaining whitespace. @@ -871,6 +902,18 @@ int main(int argc, char **argv) */ cmdline_run_saved(conf); + /* + * If we have no better ideas for the remote username, use the local + * one, as 'ssh' does. + */ + if (conf_get_str(conf, CONF_username)[0] == '\0') { + char *user = get_username(); + if (user) { + conf_set_str(conf, CONF_username, user); + sfree(user); + } + } + /* * Apply subsystem status. */ @@ -912,6 +955,11 @@ int main(int argc, char **argv) perror("pipe"); exit(1); } + /* We don't want the signal handler to block if the pipe's full. */ + nonblock(signalpipe[0]); + nonblock(signalpipe[1]); + cloexec(signalpipe[0]); + cloexec(signalpipe[1]); putty_signal(SIGWINCH, sigwinch); /* @@ -927,7 +975,7 @@ int main(int argc, char **argv) uxsel_init(); /* - * Unix Plink doesn't provide any way to add forwardings after the + * Plink doesn't provide any way to add forwardings after the * connection is set up, so if there are none now, we can safely set * the "simple" flag. */ @@ -937,6 +985,19 @@ int main(int argc, char **argv) !conf_get_str_nthstrkey(conf, CONF_portfwd, 0)) conf_set_int(conf, CONF_ssh_simple, TRUE); + if (just_test_share_exists) { + if (!back->test_for_upstream) { + fprintf(stderr, "Connection sharing not supported for connection " + "type '%s'\n", back->name); + return 1; + } + if (back->test_for_upstream(conf_get_str(conf, CONF_host), + conf_get_int(conf, CONF_port), conf)) + return 0; + else + return 1; + } + /* * Start up the connection. */ @@ -948,6 +1009,11 @@ int main(int argc, char **argv) /* nodelay is only useful if stdin is a terminal device */ int nodelay = conf_get_int(conf, CONF_tcp_nodelay) && isatty(0); + /* This is a good place for a fuzzer to fork us. */ +#ifdef __AFL_HAVE_MANUAL_CONTROL + __AFL_INIT(); +#endif + error = back->init(NULL, &backhandle, conf, conf_get_str(conf, CONF_host), conf_get_int(conf, CONF_port), @@ -970,7 +1036,7 @@ int main(int argc, char **argv) */ local_tty = (tcgetattr(STDIN_FILENO, &orig_termios) == 0); atexit(cleanup_termios); - ldisc_update(NULL, 1, 1); + frontend_echoedit_update(NULL, 1, 1); sending = FALSE; now = GETTICKCOUNT(); @@ -1062,6 +1128,9 @@ int main(int argc, char **argv) ret = select(maxfd, &rset, &wset, &xset, NULL); } + if (ret < 0 && errno == EINTR) + continue; + if (ret < 0) { perror("select"); exit(1);