};
/*
- * 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 {
unsigned char *message;
unsigned char msglen[4];
unsigned lensofar, totallen;
+ int outstanding_requests;
} a;
struct ssh_x11_channel {
Socket s;
static unsigned long ssh_pkt_getuint32(struct Packet *pkt);
static int ssh2_pkt_getbool(struct Packet *pkt);
static void ssh_pkt_getstring(struct Packet *pkt, char **p, int *length);
-static void ssh2_timer(void *ctx, long now);
-static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
- struct Packet *pktin);
+static void ssh2_timer(void *ctx, unsigned long now);
+static void do_ssh2_transport(Ssh ssh, void *vin, int inlen,
+ struct Packet *pktin);
static void ssh2_msg_unexpected(Ssh ssh, struct Packet *pktin);
struct rdpkt1_state_tag {
unsigned long incoming_data_size, outgoing_data_size, deferred_data_size;
unsigned long max_data_size;
int kex_in_progress;
- long next_rekey, last_rekey;
+ unsigned long next_rekey, last_rekey;
char *deferred_rekey_reason; /* points to STATIC string; don't free */
/*
sfree(buf);
}
-#define bombout(msg) \
- do { \
- char *text = dupprintf msg; \
- ssh_do_close(ssh, FALSE); \
- logevent(text); \
- connection_fatal(ssh->frontend, "%s", text); \
- sfree(text); \
- } while (0)
+static void bomb_out(Ssh ssh, char *text)
+{
+ ssh_do_close(ssh, FALSE);
+ logevent(text);
+ connection_fatal(ssh->frontend, "%s", text);
+ sfree(text);
+}
+
+#define bombout(msg) bomb_out(ssh, dupprintf msg)
/* Functions to leave bits out of the SSH packet log file. */
Ssh ssh = c->ssh;
void *sentreply = reply;
+ c->u.a.outstanding_requests--;
if (!sentreply) {
/* Fake SSH_AGENT_FAILURE. */
sentreply = "\0\0\0\1\5";
}
if (reply)
sfree(reply);
+ /*
+ * If we've already seen an incoming EOF but haven't sent an
+ * outgoing one, this may be the moment to send it.
+ */
+ if (c->u.a.outstanding_requests == 0 && (c->closes & CLOSES_RCVD_EOF))
+ sshfwd_write_eof(c);
}
/*
/* XXX: rport_acceptall may not represent
* what was used to open the original connection,
* since it's reconfigurable. */
- ssh2_pkt_addstring(pktout, "0.0.0.0");
+ ssh2_pkt_addstring(pktout, "");
} else {
- ssh2_pkt_addstring(pktout, "127.0.0.1");
+ ssh2_pkt_addstring(pktout, "localhost");
}
ssh2_pkt_adduint32(pktout, epf->sport);
ssh2_pkt_send(ssh, pktout);
if (epf->saddr) {
ssh2_pkt_addstring(pktout, epf->saddr);
} else if (conf_get_int(conf, CONF_rport_acceptall)) {
- ssh2_pkt_addstring(pktout, "0.0.0.0");
+ ssh2_pkt_addstring(pktout, "");
} else {
- ssh2_pkt_addstring(pktout, "127.0.0.1");
+ ssh2_pkt_addstring(pktout, "localhost");
}
ssh2_pkt_adduint32(pktout, epf->sport);
ssh2_pkt_send(ssh, pktout);
c->type = CHAN_AGENT; /* identify channel type */
c->u.a.lensofar = 0;
c->u.a.message = NULL;
+ c->u.a.outstanding_requests = 0;
add234(ssh->channels, c);
send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
PKT_INT, c->remoteid, PKT_INT, c->localid,
if (c->u.a.lensofar == c->u.a.totallen) {
void *reply;
int replylen;
+ c->u.a.outstanding_requests++;
if (agent_query(c->u.a.message,
c->u.a.totallen,
&reply, &replylen,
/*
* Handle the SSH-2 transport layer.
*/
-static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
+static void do_ssh2_transport(Ssh ssh, void *vin, int inlen,
struct Packet *pktin)
{
unsigned char *in = (unsigned char *)vin;
ssh2_pkt_send_noqueue(ssh, s->pktout);
if (!pktin)
- crWaitUntil(pktin);
+ crWaitUntilV(pktin);
/*
* Now examine the other side's KEXINIT to see what we're up
if (pktin->type != SSH2_MSG_KEXINIT) {
bombout(("expected key exchange packet from server"));
- crStop(0);
+ crStopV;
}
ssh->kex = NULL;
ssh->hostkey = NULL;
if (!ssh->kex) {
bombout(("Couldn't agree a key exchange algorithm (available: %s)",
str ? str : "(null)"));
- crStop(0);
+ crStopV;
}
/*
* Note that the server's guess is considered wrong if it doesn't match
if (!ssh->hostkey) {
bombout(("Couldn't agree a host key algorithm (available: %s)",
str ? str : "(null)"));
- crStop(0);
+ crStopV;
}
s->guessok = s->guessok &&
if (!s->cscipher_tobe) {
bombout(("Couldn't agree a client-to-server cipher (available: %s)",
str ? str : "(null)"));
- crStop(0);
+ crStopV;
}
ssh_pkt_getstring(pktin, &str, &len); /* server->client cipher */
if (!s->sccipher_tobe) {
bombout(("Couldn't agree a server-to-client cipher (available: %s)",
str ? str : "(null)"));
- crStop(0);
+ crStopV;
}
ssh_pkt_getstring(pktin, &str, &len); /* client->server mac */
ssh_dialog_callback, ssh);
if (s->dlgret < 0) {
do {
- crReturn(0);
+ crReturnV;
if (pktin) {
bombout(("Unexpected data from server while"
" waiting for user response"));
- crStop(0);
+ crStopV;
}
} while (pktin || inlen > 0);
s->dlgret = ssh->user_response;
if (s->dlgret == 0) {
ssh_disconnect(ssh, "User aborted at kex warning", NULL,
0, TRUE);
- crStop(0);
+ crStopV;
}
}
ssh_dialog_callback, ssh);
if (s->dlgret < 0) {
do {
- crReturn(0);
+ crReturnV;
if (pktin) {
bombout(("Unexpected data from server while"
" waiting for user response"));
- crStop(0);
+ crStopV;
}
} while (pktin || inlen > 0);
s->dlgret = ssh->user_response;
if (s->dlgret == 0) {
ssh_disconnect(ssh, "User aborted at cipher warning", NULL,
0, TRUE);
- crStop(0);
+ crStopV;
}
}
ssh_dialog_callback, ssh);
if (s->dlgret < 0) {
do {
- crReturn(0);
+ crReturnV;
if (pktin) {
bombout(("Unexpected data from server while"
" waiting for user response"));
- crStop(0);
+ crStopV;
}
} while (pktin || inlen > 0);
s->dlgret = ssh->user_response;
if (s->dlgret == 0) {
ssh_disconnect(ssh, "User aborted at cipher warning", NULL,
0, TRUE);
- crStop(0);
+ crStopV;
}
}
pktin->data + 5, pktin->length - 5);
if (s->ignorepkt) /* first_kex_packet_follows */
- crWaitUntil(pktin); /* Ignore packet */
+ crWaitUntilV(pktin); /* Ignore packet */
}
if (ssh->kex->main_type == KEXTYPE_DH) {
ssh2_pkt_adduint32(s->pktout, s->pbits);
ssh2_pkt_send_noqueue(ssh, s->pktout);
- crWaitUntil(pktin);
+ crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_KEX_DH_GEX_GROUP) {
bombout(("expected key exchange group packet from server"));
- crStop(0);
+ crStopV;
}
s->p = ssh2_pkt_getmp(pktin);
s->g = ssh2_pkt_getmp(pktin);
if (!s->p || !s->g) {
bombout(("unable to read mp-ints from incoming group packet"));
- crStop(0);
+ crStopV;
}
ssh->kex_ctx = dh_setup_gex(s->p, s->g);
s->kex_init_value = SSH2_MSG_KEX_DH_GEX_INIT;
ssh2_pkt_send_noqueue(ssh, s->pktout);
set_busy_status(ssh->frontend, BUSY_WAITING); /* wait for server */
- crWaitUntil(pktin);
+ crWaitUntilV(pktin);
if (pktin->type != s->kex_reply_value) {
bombout(("expected key exchange reply packet from server"));
- crStop(0);
+ crStopV;
}
set_busy_status(ssh->frontend, BUSY_CPU); /* cogitate */
ssh_pkt_getstring(pktin, &s->hostkeydata, &s->hostkeylen);
s->f = ssh2_pkt_getmp(pktin);
if (!s->f) {
bombout(("unable to parse key exchange reply packet"));
- crStop(0);
+ crStopV;
}
ssh_pkt_getstring(pktin, &s->sigdata, &s->siglen);
* RSA key exchange. First expect a KEXRSA_PUBKEY packet
* from the server.
*/
- crWaitUntil(pktin);
+ crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_KEXRSA_PUBKEY) {
bombout(("expected RSA public key packet from server"));
- crStop(0);
+ crStopV;
}
ssh_pkt_getstring(pktin, &s->hostkeydata, &s->hostkeylen);
if (!s->rsakey) {
sfree(s->rsakeydata);
bombout(("unable to parse RSA public key from server"));
- crStop(0);
+ crStopV;
}
hash_string(ssh->kex->hash, ssh->exhash, s->rsakeydata, s->rsakeylen);
ssh_rsakex_freekey(s->rsakey);
- crWaitUntil(pktin);
+ crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_KEXRSA_DONE) {
sfree(s->rsakeydata);
bombout(("expected signature packet from server"));
- crStop(0);
+ crStopV;
}
ssh_pkt_getstring(pktin, &s->sigdata, &s->siglen);
(char *)s->exchange_hash,
ssh->kex->hash->hlen)) {
bombout(("Server's host key did not match the signature supplied"));
- crStop(0);
+ crStopV;
}
/*
ssh_dialog_callback, ssh);
if (s->dlgret < 0) {
do {
- crReturn(0);
+ crReturnV;
if (pktin) {
bombout(("Unexpected data from server while waiting"
" for user host key response"));
- crStop(0);
+ crStopV;
}
} while (pktin || inlen > 0);
s->dlgret = ssh->user_response;
if (s->dlgret == 0) {
ssh_disconnect(ssh, "User aborted at host key verification", NULL,
0, TRUE);
- crStop(0);
+ crStopV;
}
if (!s->got_session_id) { /* don't bother logging this in rekeys */
logevent("Host key fingerprint is:");
/*
* Expect SSH2_MSG_NEWKEYS from server.
*/
- crWaitUntil(pktin);
+ crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_NEWKEYS) {
bombout(("expected new-keys packet from server"));
- crStop(0);
+ crStopV;
}
ssh->incoming_data_size = 0; /* start counting from here */
*/
do_ssh2_authconn(ssh, NULL, 0, NULL);
}
- crReturn(1);
+ crReturnV;
}
if (pktin) {
logevent("Server initiated key re-exchange");
}
goto begin_key_exchange;
- crFinish(1);
+ crFinishV;
}
/*
}
/*
+ * 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.
if (c->u.a.lensofar == c->u.a.totallen) {
void *reply;
int replylen;
+ c->u.a.outstanding_requests++;
if (agent_query(c->u.a.message,
c->u.a.totallen,
&reply, &replylen,
if (c->type == CHAN_X11) {
x11_send_eof(c->u.x11.s);
} else if (c->type == CHAN_AGENT) {
- /* Manufacture an outgoing EOF in response to the incoming one. */
- sshfwd_write_eof(c);
+ if (c->u.a.outstanding_requests == 0) {
+ /* Manufacture an outgoing EOF in response to the incoming one. */
+ sshfwd_write_eof(c);
+ }
} else if (c->type == CHAN_SOCKDATA) {
pfd_send_eof(c->u.pfd.s);
} else if (c->type == CHAN_MAINSESSION) {
else {
c->type = CHAN_AGENT; /* identify channel type */
c->u.a.lensofar = 0;
+ c->u.a.outstanding_requests = 0;
}
} else {
error = "Unsupported channel type requested";
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;
-
- crWaitUntilV(pktin);
+ /* 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);
- 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;
}
* 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);
*/
if (conf_get_int(ssh->conf, CONF_ssh_no_shell)) {
ssh->mainchan = NULL;
- } else if (*conf_get_str(ssh->conf, CONF_ssh_nc_host)) {
- /*
- * Just start a direct-tcpip channel and use it as the main
- * channel.
- */
+ } else {
ssh->mainchan = snew(struct ssh_channel);
ssh->mainchan->ssh = ssh;
ssh2_channel_init(ssh->mainchan);
- logeventf(ssh,
- "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 */
- 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));
- /*
- * There's nothing meaningful to put in the originator
- * fields, but some servers insist on syntactically correct
- * information.
- */
- ssh2_pkt_addstring(s->pktout, "0.0.0.0");
- ssh2_pkt_adduint32(s->pktout, 0);
- ssh2_pkt_send(ssh, s->pktout);
- crWaitUntilV(pktin);
- if (pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
- bombout(("Server refused to open a direct-tcpip channel"));
- crStopV;
- /* FIXME: error data comes back in FAILURE packet */
- }
- if (ssh_pkt_getuint32(pktin) != ssh->mainchan->localid) {
- bombout(("Server's channel confirmation cited wrong channel"));
- crStopV;
+ if (*conf_get_str(ssh->conf, CONF_ssh_nc_host)) {
+ /*
+ * Just start a direct-tcpip channel and use it as the main
+ * channel.
+ */
+ ssh_send_port_open(ssh->mainchan,
+ conf_get_str(ssh->conf, CONF_ssh_nc_host),
+ conf_get_int(ssh->conf, CONF_ssh_nc_port),
+ "main channel");
+ ssh->ncmode = TRUE;
+ } else {
+ s->pktout = ssh2_chanopen_init(ssh->mainchan, "session");
+ logevent("Opening session as main channel");
+ ssh2_pkt_send(ssh, s->pktout);
+ ssh->ncmode = FALSE;
}
- ssh->mainchan->remoteid = ssh_pkt_getuint32(pktin);
- ssh->mainchan->halfopen = FALSE;
- ssh->mainchan->type = CHAN_MAINSESSION;
- ssh->mainchan->v.v2.remwindow = ssh_pkt_getuint32(pktin);
- ssh->mainchan->v.v2.remmaxpkt = ssh_pkt_getuint32(pktin);
- add234(ssh->channels, ssh->mainchan);
- update_specials_menu(ssh->frontend);
- logevent("Opened direct-tcpip channel");
- ssh->ncmode = TRUE;
- } else {
- 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 */
- ssh2_pkt_send(ssh, s->pktout);
crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
- bombout(("Server refused to open a session"));
+ bombout(("Server refused to open channel"));
crStopV;
/* FIXME: error data comes back in FAILURE packet */
}
ssh->mainchan->v.v2.remmaxpkt = ssh_pkt_getuint32(pktin);
add234(ssh->channels, ssh->mainchan);
update_specials_menu(ssh->frontend);
- logevent("Opened channel for session");
- ssh->ncmode = FALSE;
+ logevent("Opened main channel");
}
/*
*/
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;
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)
ssh->packet_dispatch[SSH2_MSG_DEBUG] = ssh2_msg_debug;
}
-static void ssh2_timer(void *ctx, long now)
+static void ssh2_timer(void *ctx, unsigned long now)
{
Ssh ssh = (Ssh)ctx;
return;
if (!ssh->kex_in_progress && conf_get_int(ssh->conf, CONF_ssh_rekey_time) != 0 &&
- now - ssh->next_rekey >= 0) {
+ now == ssh->next_rekey) {
do_ssh2_transport(ssh, "timeout", -1, NULL);
}
}
rekey_time = conf_get_int(conf, CONF_ssh_rekey_time);
if (conf_get_int(ssh->conf, CONF_ssh_rekey_time) != rekey_time &&
rekey_time != 0) {
- long new_next = ssh->last_rekey + rekey_time*60*TICKSPERSEC;
- long now = GETTICKCOUNT();
+ unsigned long new_next = ssh->last_rekey + rekey_time*60*TICKSPERSEC;
+ unsigned long now = GETTICKCOUNT();
- if (new_next - now < 0) {
+ if (now - ssh->last_rekey > rekey_time*60*TICKSPERSEC) {
rekeying = "timeout shortened";
} else {
ssh->next_rekey = schedule_timer(new_next - now, ssh2_timer, ssh);
Ssh ssh = c->ssh;
struct Packet *pktout;
- logeventf(ssh, "Opening forwarded connection to %s:%d", hostname, port);
+ logeventf(ssh, "Opening connection to %s:%d for %s", hostname, port, org);
if (ssh->version == 1) {
send_packet(ssh, SSH1_MSG_PORT_OPEN,
/* PKT_STR, <org:orgport>, */
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);
/*