X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/3bb2f32264efd14ce4a39bea59be27c039646f6c..6b0eeb4e4c9ecbff8eda72c5a1b49a448d6bbf3a:/ssh.c diff --git a/ssh.c b/ssh.c index b2abec47..c37762ed 100644 --- a/ssh.c +++ b/ssh.c @@ -1983,6 +1983,7 @@ static int do_ssh_init(Ssh ssh, unsigned char c) ssh->version = 1; ssh->s_rdpkt = ssh1_rdpkt; } + update_specials_menu(ssh->frontend); ssh->state = SSH_STATE_BEFORE_SIZE; sfree(s->vstring); @@ -3148,30 +3149,34 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) if (n < 255) sports[n++] = *ssh->portfwd_strptr++; } sports[n] = 0; - if (*ssh->portfwd_strptr == '\t') - ssh->portfwd_strptr++; - n = 0; - while (*ssh->portfwd_strptr && *ssh->portfwd_strptr != ':') { - if (n < 255) host[n++] = *ssh->portfwd_strptr++; - } - host[n] = 0; - if (*ssh->portfwd_strptr == ':') + if (type != 'D') { + if (*ssh->portfwd_strptr == '\t') + ssh->portfwd_strptr++; + n = 0; + while (*ssh->portfwd_strptr && *ssh->portfwd_strptr != ':') { + if (n < 255) host[n++] = *ssh->portfwd_strptr++; + } + host[n] = 0; + if (*ssh->portfwd_strptr == ':') + ssh->portfwd_strptr++; + n = 0; + while (*ssh->portfwd_strptr) { + if (n < 255) dports[n++] = *ssh->portfwd_strptr++; + } + dports[n] = 0; ssh->portfwd_strptr++; - n = 0; - while (*ssh->portfwd_strptr) { - if (n < 255) dports[n++] = *ssh->portfwd_strptr++; - } - dports[n] = 0; - ssh->portfwd_strptr++; - dport = atoi(dports); - dserv = 0; - if (dport == 0) { - dserv = 1; - dport = net_service_lookup(dports); - if (!dport) { - logeventf(ssh, "Service lookup failed for" - " destination port \"%s\"", dports); + dport = atoi(dports); + dserv = 0; + if (dport == 0) { + dserv = 1; + dport = net_service_lookup(dports); + if (!dport) { + logeventf(ssh, "Service lookup failed for" + " destination port \"%s\"", dports); + } } + } else { + while (*ssh->portfwd_strptr) ssh->portfwd_strptr++; } sport = atoi(sports); sserv = 0; @@ -3196,6 +3201,15 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt) host, (int)(dserv ? strlen(dports) : 0), dports, dserv, "(", dport, dserv, ")"); + } else if (type == 'D') { + pfd_addforward(NULL, -1, *saddr ? saddr : NULL, + sport, ssh, &ssh->cfg); + logeventf(ssh, "Local port %.*s%.*s%.*s%.*s%d%.*s" + " doing SOCKS dynamic forwarding", + (int)(*saddr?strlen(saddr):0), *saddr?saddr:NULL, + (int)(*saddr?1:0), ":", + (int)(sserv ? strlen(sports) : 0), sports, + sserv, "(", sport, sserv, ")"); } else { struct ssh_rportfwd *pf; pf = snew(struct ssh_rportfwd); @@ -5229,30 +5243,34 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) if (n < 255) sports[n++] = *ssh->portfwd_strptr++; } sports[n] = 0; - if (*ssh->portfwd_strptr == '\t') - ssh->portfwd_strptr++; - n = 0; - while (*ssh->portfwd_strptr && *ssh->portfwd_strptr != ':') { - if (n < 255) host[n++] = *ssh->portfwd_strptr++; - } - host[n] = 0; - if (*ssh->portfwd_strptr == ':') + if (type != 'D') { + if (*ssh->portfwd_strptr == '\t') + ssh->portfwd_strptr++; + n = 0; + while (*ssh->portfwd_strptr && *ssh->portfwd_strptr != ':') { + if (n < 255) host[n++] = *ssh->portfwd_strptr++; + } + host[n] = 0; + if (*ssh->portfwd_strptr == ':') + ssh->portfwd_strptr++; + n = 0; + while (*ssh->portfwd_strptr) { + if (n < 255) dports[n++] = *ssh->portfwd_strptr++; + } + dports[n] = 0; ssh->portfwd_strptr++; - n = 0; - while (*ssh->portfwd_strptr) { - if (n < 255) dports[n++] = *ssh->portfwd_strptr++; - } - dports[n] = 0; - ssh->portfwd_strptr++; - dport = atoi(dports); - dserv = 0; - if (dport == 0) { - dserv = 1; - dport = net_service_lookup(dports); - if (!dport) { - logeventf(ssh, "Service lookup failed for destination" - " port \"%s\"", dports); + dport = atoi(dports); + dserv = 0; + if (dport == 0) { + dserv = 1; + dport = net_service_lookup(dports); + if (!dport) { + logeventf(ssh, "Service lookup failed for destination" + " port \"%s\"", dports); + } } + } else { + while (*ssh->portfwd_strptr) ssh->portfwd_strptr++; } sport = atoi(sports); sserv = 0; @@ -5277,6 +5295,15 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) host, (int)(dserv ? strlen(dports) : 0), dports, dserv, "(", dport, dserv, ")"); + } else if (type == 'D') { + pfd_addforward(NULL, -1, *saddr ? saddr : NULL, + sport, ssh, &ssh->cfg); + logeventf(ssh, "Local port %.*s%.*s%.*s%.*s%d%.*s" + " doing SOCKS dynamic forwarding", + (int)(*saddr?strlen(saddr):0), *saddr?saddr:NULL, + (int)(*saddr?1:0), ":", + (int)(sserv ? strlen(sports) : 0), sports, + sserv, "(", sport, sserv, ")"); } else { struct ssh_rportfwd *pf; pf = snew(struct ssh_rportfwd); @@ -5807,7 +5834,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) int typelen; char *peeraddr; int peeraddrlen; - int port; + int peerport; char *error = NULL; struct ssh_channel *c; unsigned remid, winsize, pktsize; @@ -5818,18 +5845,18 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) remid = ssh2_pkt_getuint32(ssh); winsize = ssh2_pkt_getuint32(ssh); pktsize = ssh2_pkt_getuint32(ssh); - ssh2_pkt_getstring(ssh, &peeraddr, &peeraddrlen); - port = ssh2_pkt_getuint32(ssh); if (typelen == 3 && !memcmp(type, "x11", 3)) { char *addrstr = snewn(peeraddrlen+1, char); memcpy(addrstr, peeraddr, peeraddrlen); peeraddr[peeraddrlen] = '\0'; + ssh2_pkt_getstring(ssh, &peeraddr, &peeraddrlen); + peerport = ssh2_pkt_getuint32(ssh); if (!ssh->X11_fwd_enabled) error = "X11 forwarding is not enabled"; else if (x11_init(&c->u.x11.s, ssh->cfg.x11_display, c, - ssh->x11auth, addrstr, port, + ssh->x11auth, addrstr, peerport, &ssh->cfg) != NULL) { error = "Unable to open an X11 connection"; } else { @@ -5844,6 +5871,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt) int dummylen; ssh2_pkt_getstring(ssh, &dummy, &dummylen);/* skip address */ pf.sport = ssh2_pkt_getuint32(ssh); + ssh2_pkt_getstring(ssh, &peeraddr, &peeraddrlen); + peerport = ssh2_pkt_getuint32(ssh); realpf = find234(ssh->rportfwds, &pf, NULL); if (realpf == NULL) { error = "Remote port is not recognised"; @@ -5967,6 +5996,7 @@ static char *ssh_init(void *frontend_handle, void **backend_handle, ssh = snew(struct ssh_tag); ssh->cfg = *cfg; /* STRUCTURE COPY */ + ssh->version = 0; /* when not ready yet */ ssh->s = NULL; ssh->cipher = NULL; ssh->v1_cipher_ctx = NULL; @@ -6213,6 +6243,31 @@ static void ssh_size(void *handle, int width, int height) } /* + * Return a list of the special codes that make sense in this + * protocol. + */ +static const struct telnet_special *ssh_get_specials(void *handle) +{ + Ssh ssh = (Ssh) handle; + + if (ssh->version == 1) { + static const struct telnet_special ssh1_specials[] = { + {"IGNORE message", TS_NOP}, + {NULL, 0} + }; + return ssh1_specials; + } else if (ssh->version == 2) { + static const struct telnet_special ssh2_specials[] = { + {"Break", TS_BRK}, + {"IGNORE message", TS_NOP}, + {NULL, 0} + }; + return ssh2_specials; + } else + return NULL; +} + +/* * Send Telnet special codes. TS_EOF is useful for `plink', so you * can send an EOF and collect resulting output (e.g. `plink * hostname sort'). @@ -6239,7 +6294,7 @@ static void ssh_special(void *handle, Telnet_Special code) ssh2_pkt_send(ssh); } logevent("Sent EOF message"); - } else if (code == TS_PING) { + } else if (code == TS_PING || code == TS_NOP) { if (ssh->state == SSH_STATE_CLOSED || ssh->state == SSH_STATE_PREPACKET) return; if (ssh->version == 1) { @@ -6250,6 +6305,19 @@ static void ssh_special(void *handle, Telnet_Special code) ssh2_pkt_addstring_start(ssh); ssh2_pkt_send(ssh); } + } else if (code == TS_BRK) { + if (ssh->state == SSH_STATE_CLOSED + || ssh->state == SSH_STATE_PREPACKET) return; + if (ssh->version == 1) { + logevent("Unable to send BREAK signal in SSH1"); + } else { + ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST); + ssh2_pkt_adduint32(ssh, ssh->mainchan->remoteid); + ssh2_pkt_addstring(ssh, "break"); + ssh2_pkt_addbool(ssh, 0); + ssh2_pkt_adduint32(ssh, 0); /* default break length */ + ssh2_pkt_send(ssh); + } } else { /* do nothing */ } @@ -6390,6 +6458,7 @@ Backend ssh_backend = { ssh_sendbuffer, ssh_size, ssh_special, + ssh_get_specials, ssh_socket, ssh_return_exitcode, ssh_sendok,