#define crState(t) crStateP(t, ssh->t)
#define crFinish(z) } *crLine = 0; return (z); }
#define crFinishV } *crLine = 0; return; }
-#define crFinishFree(z, s) } *crLine = 0; sfree(s); return (z); }
-#define crFinishFreeV(s) } *crLine = 0; sfree(s); return; }
+#define crFinishFree(z) } sfree(s); return (z); }
+#define crFinishFreeV } sfree(s); return; }
#define crReturn(z) \
do {\
*crLine =__LINE__; return (z); case __LINE__:;\
};
/*
- * 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 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 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 {
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. */
* follows it, or 'A' indicating that we should pass the
* value through from the local environment via get_ttymode.
*/
- if (val[0] == 'A')
+ if (val[0] == 'A') {
val = get_ttymode(ssh->frontend, key);
- else
- val++; /* skip the 'V' */
- if (val)
- do_mode(data, key, val);
+ if (val) {
+ do_mode(data, key, val);
+ sfree(val);
+ }
+ } else
+ do_mode(data, key, val + 1); /* skip the 'V' */
}
}
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);
}
/*
void sshfwd_unclean_close(struct ssh_channel *c)
{
Ssh ssh = c->ssh;
- struct Packet *pktout;
if (ssh->state == SSH_STATE_CLOSED)
return;
- if (!(c->closes & CLOSES_SENT_CLOSE)) {
- pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE);
- ssh2_pkt_adduint32(pktout, c->remoteid);
- ssh2_pkt_send(ssh, pktout);
- c->closes |= CLOSES_SENT_EOF | CLOSES_SENT_CLOSE;
- }
-
switch (c->type) {
case CHAN_X11:
x11_close(c->u.x11.s);
+ logevent("Forwarded X11 connection terminated due to local error");
break;
case CHAN_SOCKDATA:
case CHAN_SOCKDATA_DORMANT:
pfd_close(c->u.pfd.s);
+ logevent("Forwarded port closed due to local error");
break;
}
c->type = CHAN_ZOMBIE;
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,
Ssh ssh = c->ssh;
struct Packet *pktout;
- if ((c->closes & (CLOSES_SENT_EOF | CLOSES_RCVD_EOF | CLOSES_SENT_CLOSE))
- == (CLOSES_SENT_EOF | CLOSES_RCVD_EOF) && !c->v.v2.chanreq_head) {
+ if ((!((CLOSES_SENT_EOF | CLOSES_RCVD_EOF) & ~c->closes) ||
+ c->type == CHAN_ZOMBIE) &&
+ !c->v.v2.chanreq_head &&
+ !(c->closes & CLOSES_SENT_CLOSE)) {
/*
- * We have both sent and received EOF, and we have no
- * outstanding channel requests, which means the
- * channel is in final wind-up. But we haven't sent CLOSE, so
- * let's do so now.
+ * We have both sent and received EOF (or the channel is a
+ * zombie), and we have no outstanding channel requests, which
+ * means the channel is in final wind-up. But we haven't sent
+ * CLOSE, so let's do so now.
*/
pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE);
ssh2_pkt_adduint32(pktout, c->remoteid);
ssh2_pkt_send(ssh, pktout);
- c->closes |= CLOSES_SENT_CLOSE;
+ c->closes |= CLOSES_SENT_EOF | CLOSES_SENT_CLOSE;
}
if (!((CLOSES_SENT_CLOSE | CLOSES_RCVD_CLOSE) & ~c->closes)) {
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(s);
+
+ 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(s);
+
+ 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(s);
+
+ crFinishFreeV;
}
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);
}
}
out:;
- crFinishFreeV(s);
+ crFinishFreeV;
}
/*
"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));
/*
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) {
*/
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)
/* 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);
/*