X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/0b106f61ff2b8b7a9f294b4a9cf9ebfedb646afc..4a62c66db92c9692b5e45566f3dd85455825317c:/ssh.c diff --git a/ssh.c b/ssh.c index 8b73da4c..b4d3884b 100644 --- a/ssh.c +++ b/ssh.c @@ -589,14 +589,6 @@ struct outstanding_channel_request { }; /* - * little structure to keep track of outstanding WINDOW_ADJUSTs - */ -struct winadj { - struct winadj *next; - unsigned size; -}; - -/* * 2-3-4 tree storing channels. */ struct ssh_channel { @@ -6580,6 +6572,21 @@ static void ssh2_channel_init(struct ssh_channel *c) } /* + * Construct the common parts of a CHANNEL_OPEN. + */ +static struct Packet *ssh2_chanopen_init(struct ssh_channel *c, char *type) +{ + struct Packet *pktout; + + pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN); + ssh2_pkt_addstring(pktout, type); + ssh2_pkt_adduint32(pktout, c->localid); + ssh2_pkt_adduint32(pktout, c->v.v2.locwindow);/* our window size */ + ssh2_pkt_adduint32(pktout, OUR_V2_MAXPKT); /* our max pkt size */ + return pktout; +} + +/* * CHANNEL_FAILURE doesn't come with any indication of what message * caused it, so we have to keep track of the outstanding * CHANNEL_REQUESTs ourselves. @@ -7468,136 +7475,126 @@ static void ssh2_send_ttymode(void *data, char *mode, char *val) ssh2_pkt_adduint32(pktout, arg); } -static void ssh2_maybe_setup_x11(struct ssh_channel *c, struct Packet *pktin, - void *ctx) +static void ssh2_setup_x11(struct ssh_channel *c, struct Packet *pktin, + void *ctx) { - struct ssh2_maybe_setup_x11_state { + struct ssh2_setup_x11_state { int crLine; }; Ssh ssh = c->ssh; struct Packet *pktout; - crStateP(ssh2_maybe_setup_x11_state, ctx); + crStateP(ssh2_setup_x11_state, ctx); crBeginState; + logevent("Requesting X11 forwarding"); + pktout = ssh2_chanreq_init(ssh->mainchan, "x11-req", + ssh2_setup_x11, s); + ssh2_pkt_addbool(pktout, 0); /* many connections */ + ssh2_pkt_addstring(pktout, ssh->x11disp->remoteauthprotoname); /* - * Potentially enable X11 forwarding. + * Note that while we blank the X authentication data here, we don't + * take any special action to blank the start of an X11 channel, + * so using MIT-MAGIC-COOKIE-1 and actually opening an X connection + * without having session blanking enabled is likely to leak your + * cookie into the log. */ - if (ssh->mainchan && !ssh->ncmode && conf_get_int(ssh->conf, CONF_x11_forward) && - (ssh->x11disp = x11_setup_display(conf_get_str(ssh->conf, CONF_x11_display), - conf_get_int(ssh->conf, CONF_x11_auth), ssh->conf))) { - logevent("Requesting X11 forwarding"); - pktout = ssh2_chanreq_init(ssh->mainchan, "x11-req", - ssh2_maybe_setup_x11, s); - ssh2_pkt_addbool(pktout, 0); /* many connections */ - ssh2_pkt_addstring(pktout, ssh->x11disp->remoteauthprotoname); - /* - * Note that while we blank the X authentication data here, we don't - * take any special action to blank the start of an X11 channel, - * so using MIT-MAGIC-COOKIE-1 and actually opening an X connection - * without having session blanking enabled is likely to leak your - * cookie into the log. - */ - dont_log_password(ssh, pktout, PKTLOG_BLANK); - ssh2_pkt_addstring(pktout, ssh->x11disp->remoteauthdatastring); - end_log_omission(ssh, pktout); - ssh2_pkt_adduint32(pktout, ssh->x11disp->screennum); - ssh2_pkt_send(ssh, pktout); + dont_log_password(ssh, pktout, PKTLOG_BLANK); + ssh2_pkt_addstring(pktout, ssh->x11disp->remoteauthdatastring); + end_log_omission(ssh, pktout); + ssh2_pkt_adduint32(pktout, ssh->x11disp->screennum); + ssh2_pkt_send(ssh, pktout); - crWaitUntilV(pktin); + crWaitUntilV(pktin); - if (pktin) { - if (pktin->type == SSH2_MSG_CHANNEL_SUCCESS) { - logevent("X11 forwarding enabled"); - ssh->X11_fwd_enabled = TRUE; - } else - logevent("X11 forwarding refused"); - } + if (pktin) { + if (pktin->type == SSH2_MSG_CHANNEL_SUCCESS) { + logevent("X11 forwarding enabled"); + ssh->X11_fwd_enabled = TRUE; + } else + logevent("X11 forwarding refused"); } + crFinishFreeV; } -static void ssh2_maybe_setup_agent(struct ssh_channel *c, struct Packet *pktin, +static void ssh2_setup_agent(struct ssh_channel *c, struct Packet *pktin, void *ctx) { - struct ssh2_maybe_setup_agent_state { + struct ssh2_setup_agent_state { int crLine; }; Ssh ssh = c->ssh; struct Packet *pktout; - crStateP(ssh2_maybe_setup_agent_state, ctx); + crStateP(ssh2_setup_agent_state, ctx); crBeginState; - if (ssh->mainchan && !ssh->ncmode && conf_get_int(ssh->conf, CONF_agentfwd) && agent_exists()) { - logevent("Requesting OpenSSH-style agent forwarding"); - pktout = ssh2_chanreq_init(ssh->mainchan, "auth-agent-req@openssh.com", - ssh2_maybe_setup_agent, s); - ssh2_pkt_send(ssh, pktout); + logevent("Requesting OpenSSH-style agent forwarding"); + pktout = ssh2_chanreq_init(ssh->mainchan, "auth-agent-req@openssh.com", + ssh2_setup_agent, s); + ssh2_pkt_send(ssh, pktout); - crWaitUntilV(pktin); + crWaitUntilV(pktin); - if (pktin) { - if (pktin->type == SSH2_MSG_CHANNEL_SUCCESS) { - logevent("Agent forwarding enabled"); - ssh->agentfwd_enabled = TRUE; - } else - logevent("Agent forwarding refused"); - } + if (pktin) { + if (pktin->type == SSH2_MSG_CHANNEL_SUCCESS) { + logevent("Agent forwarding enabled"); + ssh->agentfwd_enabled = TRUE; + } else + logevent("Agent forwarding refused"); } + crFinishFreeV; } -static void ssh2_maybe_setup_pty(struct ssh_channel *c, struct Packet *pktin, +static void ssh2_setup_pty(struct ssh_channel *c, struct Packet *pktin, void *ctx) { - struct ssh2_maybe_setup_pty_state { + struct ssh2_setup_pty_state { int crLine; }; Ssh ssh = c->ssh; struct Packet *pktout; - crStateP(ssh2_maybe_setup_pty_state, ctx); + crStateP(ssh2_setup_pty_state, ctx); crBeginState; - if (ssh->mainchan && !ssh->ncmode && !conf_get_int(ssh->conf, CONF_nopty)) { - /* Unpick the terminal-speed string. */ - /* XXX perhaps we should allow no speeds to be sent. */ - ssh->ospeed = 38400; ssh->ispeed = 38400; /* last-resort defaults */ - sscanf(conf_get_str(ssh->conf, CONF_termspeed), "%d,%d", &ssh->ospeed, &ssh->ispeed); - /* Build the pty request. */ - pktout = ssh2_chanreq_init(ssh->mainchan, "pty-req", - ssh2_maybe_setup_pty, s); - ssh2_pkt_addstring(pktout, conf_get_str(ssh->conf, CONF_termtype)); - ssh2_pkt_adduint32(pktout, ssh->term_width); - ssh2_pkt_adduint32(pktout, ssh->term_height); - ssh2_pkt_adduint32(pktout, 0); /* pixel width */ - ssh2_pkt_adduint32(pktout, 0); /* pixel height */ - ssh2_pkt_addstring_start(pktout); - parse_ttymodes(ssh, ssh2_send_ttymode, (void *)pktout); - ssh2_pkt_addbyte(pktout, SSH2_TTY_OP_ISPEED); - ssh2_pkt_adduint32(pktout, ssh->ispeed); - ssh2_pkt_addbyte(pktout, SSH2_TTY_OP_OSPEED); - ssh2_pkt_adduint32(pktout, ssh->ospeed); - ssh2_pkt_addstring_data(pktout, "\0", 1); /* TTY_OP_END */ - ssh2_pkt_send(ssh, pktout); - ssh->state = SSH_STATE_INTERMED; + /* Unpick the terminal-speed string. */ + /* XXX perhaps we should allow no speeds to be sent. */ + ssh->ospeed = 38400; ssh->ispeed = 38400; /* last-resort defaults */ + sscanf(conf_get_str(ssh->conf, CONF_termspeed), "%d,%d", &ssh->ospeed, &ssh->ispeed); + /* Build the pty request. */ + pktout = ssh2_chanreq_init(ssh->mainchan, "pty-req", + ssh2_setup_pty, s); + ssh2_pkt_addstring(pktout, conf_get_str(ssh->conf, CONF_termtype)); + ssh2_pkt_adduint32(pktout, ssh->term_width); + ssh2_pkt_adduint32(pktout, ssh->term_height); + ssh2_pkt_adduint32(pktout, 0); /* pixel width */ + ssh2_pkt_adduint32(pktout, 0); /* pixel height */ + ssh2_pkt_addstring_start(pktout); + parse_ttymodes(ssh, ssh2_send_ttymode, (void *)pktout); + ssh2_pkt_addbyte(pktout, SSH2_TTY_OP_ISPEED); + ssh2_pkt_adduint32(pktout, ssh->ispeed); + ssh2_pkt_addbyte(pktout, SSH2_TTY_OP_OSPEED); + ssh2_pkt_adduint32(pktout, ssh->ospeed); + ssh2_pkt_addstring_data(pktout, "\0", 1); /* TTY_OP_END */ + ssh2_pkt_send(ssh, pktout); + ssh->state = SSH_STATE_INTERMED; - crWaitUntilV(pktin); + crWaitUntilV(pktin); - if (pktin) { - if (pktin->type == SSH2_MSG_CHANNEL_SUCCESS) { - logeventf(ssh, "Allocated pty (ospeed %dbps, ispeed %dbps)", - ssh->ospeed, ssh->ispeed); - ssh->got_pty = TRUE; - } else { - c_write_str(ssh, "Server refused to allocate pty\r\n"); - ssh->editing = ssh->echoing = 1; - } - } - } else { - ssh->editing = ssh->echoing = 1; + if (pktin) { + if (pktin->type == SSH2_MSG_CHANNEL_SUCCESS) { + logeventf(ssh, "Allocated pty (ospeed %dbps, ispeed %dbps)", + ssh->ospeed, ssh->ispeed); + ssh->got_pty = TRUE; + } else { + c_write_str(ssh, "Server refused to allocate pty\r\n"); + ssh->editing = ssh->echoing = 1; + } } + crFinishFreeV; } @@ -7621,7 +7618,7 @@ static void ssh2_setup_env(struct ssh_channel *c, struct Packet *pktin, * then wait for a whole bunch of successes or failures. */ s->num_env = 0; - if (ssh->mainchan && !ssh->ncmode) { + { char *key, *val; for (val = conf_get_str_strs(ssh->conf, CONF_environmt, NULL, &key); @@ -9131,11 +9128,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, "Opening direct-tcpip channel to %s:%d in place of session", conf_get_str(ssh->conf, CONF_ssh_nc_host), conf_get_int(ssh->conf, CONF_ssh_nc_port)); - s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN); - ssh2_pkt_addstring(s->pktout, "direct-tcpip"); - ssh2_pkt_adduint32(s->pktout, ssh->mainchan->localid); - ssh2_pkt_adduint32(s->pktout, ssh->mainchan->v.v2.locwindow);/* our window size */ - ssh2_pkt_adduint32(s->pktout, OUR_V2_MAXPKT); /* our max pkt size */ + s->pktout = ssh2_chanopen_init(ssh->mainchan, "direct-tcpip"); ssh2_pkt_addstring(s->pktout, conf_get_str(ssh->conf, CONF_ssh_nc_host)); ssh2_pkt_adduint32(s->pktout, conf_get_int(ssh->conf, CONF_ssh_nc_port)); /* @@ -9170,11 +9163,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, ssh->mainchan = snew(struct ssh_channel); ssh->mainchan->ssh = ssh; ssh2_channel_init(ssh->mainchan); - s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN); - ssh2_pkt_addstring(s->pktout, "session"); - ssh2_pkt_adduint32(s->pktout, ssh->mainchan->localid); - ssh2_pkt_adduint32(s->pktout, ssh->mainchan->v.v2.locwindow);/* our window size */ - ssh2_pkt_adduint32(s->pktout, OUR_V2_MAXPKT); /* our max pkt size */ + s->pktout = ssh2_chanopen_init(ssh->mainchan, "session"); ssh2_pkt_send(ssh, s->pktout); crWaitUntilV(pktin); if (pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) { @@ -9236,88 +9225,92 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, */ ssh_setup_portfwd(ssh, ssh->conf); - /* - * Send the CHANNEL_REQUESTS for the main channel. Each one is - * handled by its own little asynchronous co-routine. - */ + if (ssh->mainchan && !ssh->ncmode) { + /* + * Send the CHANNEL_REQUESTS for the main session channel. + * Each one is handled by its own little asynchronous + * co-routine. + */ - /* - * Potentially enable X11 forwarding. - */ - ssh2_maybe_setup_x11(ssh->mainchan, NULL, NULL); + /* Potentially enable X11 forwarding. */ + if (conf_get_int(ssh->conf, CONF_x11_forward) && + (ssh->x11disp = + x11_setup_display(conf_get_str(ssh->conf, CONF_x11_display), + conf_get_int(ssh->conf, CONF_x11_auth), + ssh->conf))) + ssh2_setup_x11(ssh->mainchan, NULL, NULL); - /* - * Potentially enable agent forwarding. - */ - ssh2_maybe_setup_agent(ssh->mainchan, NULL, NULL); + /* Potentially enable agent forwarding. */ + if (conf_get_int(ssh->conf, CONF_agentfwd) && agent_exists()) + ssh2_setup_agent(ssh->mainchan, NULL, NULL); - /* - * Now allocate a pty for the session. - */ - ssh2_maybe_setup_pty(ssh->mainchan, NULL, NULL); + /* Now allocate a pty for the session. */ + if (!conf_get_int(ssh->conf, CONF_nopty)) + ssh2_setup_pty(ssh->mainchan, NULL, NULL); - /* - * Send environment variables. - */ - ssh2_setup_env(ssh->mainchan, NULL, NULL); + /* Send environment variables. */ + ssh2_setup_env(ssh->mainchan, NULL, NULL); - /* - * Start a shell or a remote command. We may have to attempt - * this twice if the config data has provided a second choice - * of command. - */ - if (ssh->mainchan && !ssh->ncmode) while (1) { - int subsys; - char *cmd; + /* + * Start a shell or a remote command. We may have to attempt + * this twice if the config data has provided a second choice + * of command. + */ + while (1) { + int subsys; + char *cmd; - if (ssh->fallback_cmd) { - subsys = conf_get_int(ssh->conf, CONF_ssh_subsys2); - cmd = conf_get_str(ssh->conf, CONF_remote_cmd2); - } else { - subsys = conf_get_int(ssh->conf, CONF_ssh_subsys); - cmd = conf_get_str(ssh->conf, CONF_remote_cmd); - } + if (ssh->fallback_cmd) { + subsys = conf_get_int(ssh->conf, CONF_ssh_subsys2); + cmd = conf_get_str(ssh->conf, CONF_remote_cmd2); + } else { + subsys = conf_get_int(ssh->conf, CONF_ssh_subsys); + cmd = conf_get_str(ssh->conf, CONF_remote_cmd); + } - if (subsys) { - s->pktout = ssh2_chanreq_init(ssh->mainchan, "subsystem", - ssh2_response_authconn, NULL); - ssh2_pkt_addstring(s->pktout, cmd); - } else if (*cmd) { - s->pktout = ssh2_chanreq_init(ssh->mainchan, "exec", - ssh2_response_authconn, NULL); - ssh2_pkt_addstring(s->pktout, cmd); - } else { - s->pktout = ssh2_chanreq_init(ssh->mainchan, "shell", - ssh2_response_authconn, NULL); - } - ssh2_pkt_send(ssh, s->pktout); + if (subsys) { + s->pktout = ssh2_chanreq_init(ssh->mainchan, "subsystem", + ssh2_response_authconn, NULL); + ssh2_pkt_addstring(s->pktout, cmd); + } else if (*cmd) { + s->pktout = ssh2_chanreq_init(ssh->mainchan, "exec", + ssh2_response_authconn, NULL); + ssh2_pkt_addstring(s->pktout, cmd); + } else { + s->pktout = ssh2_chanreq_init(ssh->mainchan, "shell", + ssh2_response_authconn, NULL); + } + ssh2_pkt_send(ssh, s->pktout); - crWaitUntilV(pktin); + crWaitUntilV(pktin); - if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) { - if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) { - bombout(("Unexpected response to shell/command request:" - " packet type %d", pktin->type)); + if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) { + if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) { + bombout(("Unexpected response to shell/command request:" + " packet type %d", pktin->type)); + crStopV; + } + /* + * We failed to start the command. If this is the + * fallback command, we really are finished; if it's + * not, and if the fallback command exists, try falling + * back to it before complaining. + */ + if (!ssh->fallback_cmd && + *conf_get_str(ssh->conf, CONF_remote_cmd2)) { + logevent("Primary command failed; attempting fallback"); + ssh->fallback_cmd = TRUE; + continue; + } + bombout(("Server refused to start a shell/command")); crStopV; + } else { + logevent("Started a shell/command"); } - /* - * We failed to start the command. If this is the - * fallback command, we really are finished; if it's - * not, and if the fallback command exists, try falling - * back to it before complaining. - */ - if (!ssh->fallback_cmd && - *conf_get_str(ssh->conf, CONF_remote_cmd2)) { - logevent("Primary command failed; attempting fallback"); - ssh->fallback_cmd = TRUE; - continue; - } - bombout(("Server refused to start a shell/command")); - crStopV; - } else { - logevent("Started a shell/command"); + break; } - break; + } else { + ssh->editing = ssh->echoing = TRUE; } ssh->state = SSH_STATE_SESSION; @@ -9327,13 +9320,6 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, ssh_special(ssh, TS_EOF); /* - * All the initial channel requests are done, so install the default - * response handler. - */ - ssh->packet_dispatch[SSH2_MSG_CHANNEL_SUCCESS] = ssh2_msg_channel_response; - ssh->packet_dispatch[SSH2_MSG_CHANNEL_FAILURE] = ssh2_msg_channel_response; - - /* * Transfer data! */ if (ssh->ldisc) @@ -10168,11 +10154,7 @@ void ssh_send_port_open(void *channel, char *hostname, int port, char *org) /* PKT_STR, , */ PKT_END); } else { - pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN); - ssh2_pkt_addstring(pktout, "direct-tcpip"); - ssh2_pkt_adduint32(pktout, c->localid); - ssh2_pkt_adduint32(pktout, c->v.v2.locwindow);/* our window size */ - ssh2_pkt_adduint32(pktout, OUR_V2_MAXPKT); /* our max pkt size */ + pktout = ssh2_chanopen_init(c, "direct-tcpip"); ssh2_pkt_addstring(pktout, hostname); ssh2_pkt_adduint32(pktout, port); /*