static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen,
struct Packet *pktin);
static void ssh_channel_init(struct ssh_channel *c);
+static struct ssh_channel *ssh_channel_msg(Ssh ssh, struct Packet *pktin);
static void ssh2_channel_check_close(struct ssh_channel *c);
static void ssh_channel_destroy(struct ssh_channel *c);
static void ssh_channel_unthrottle(struct ssh_channel *c, int bufsize);
int cross_certifying;
};
+static const char *ssh_pkt_type(Ssh ssh, int type)
+{
+ if (ssh->version == 1)
+ return ssh1_pkt_type(type);
+ else
+ return ssh2_pkt_type(ssh->pkt_kctx, ssh->pkt_actx, type);
+}
+
#define logevent(s) logevent(ssh->frontend, s)
/* logevent, only printf-formatted. */
static void ssh1_msg_channel_open_confirmation(Ssh ssh, struct Packet *pktin)
{
- unsigned int remoteid = ssh_pkt_getuint32(pktin);
- unsigned int localid = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
- c = find234(ssh->channels, &remoteid, ssh_channelfind);
+ c = ssh_channel_msg(ssh, pktin);
if (c && c->type == CHAN_SOCKDATA_DORMANT) {
- c->remoteid = localid;
+ c->remoteid = ssh_pkt_getuint32(pktin);
c->halfopen = FALSE;
c->type = CHAN_SOCKDATA;
c->throttling_conn = 0;
static void ssh1_msg_channel_open_failure(Ssh ssh, struct Packet *pktin)
{
- unsigned int remoteid = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
- c = find234(ssh->channels, &remoteid, ssh_channelfind);
+ c = ssh_channel_msg(ssh, pktin);
if (c && c->type == CHAN_SOCKDATA_DORMANT) {
logevent("Forwarded connection refused by server");
pfd_close(c->u.pfd.pf);
static void ssh1_msg_channel_close(Ssh ssh, struct Packet *pktin)
{
/* Remote side closes a channel. */
- unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
- c = find234(ssh->channels, &i, ssh_channelfind);
- if (c && !c->halfopen) {
+
+ c = ssh_channel_msg(ssh, pktin);
+ if (c) {
if (pktin->type == SSH1_MSG_CHANNEL_CLOSE &&
!(c->closes & CLOSES_RCVD_EOF)) {
!(c->closes & CLOSES_RCVD_CLOSE)) {
if (!(c->closes & CLOSES_SENT_EOF)) {
- bombout(("Received CHANNEL_CLOSE_CONFIRMATION for channel %d"
- " for which we never sent CHANNEL_CLOSE\n", i));
+ bombout(("Received CHANNEL_CLOSE_CONFIRMATION for channel %u"
+ " for which we never sent CHANNEL_CLOSE\n",
+ c->localid));
}
c->closes |= CLOSES_RCVD_CLOSE;
if (!((CLOSES_SENT_CLOSE | CLOSES_RCVD_CLOSE) & ~c->closes))
ssh_channel_destroy(c);
- } else {
- bombout(("Received CHANNEL_CLOSE%s for %s channel %d\n",
- pktin->type == SSH1_MSG_CHANNEL_CLOSE ? "" :
- "_CONFIRMATION", c ? "half-open" : "nonexistent",
- i));
}
}
static void ssh1_msg_channel_data(Ssh ssh, struct Packet *pktin)
{
/* Data sent down one of our channels. */
- int i = ssh_pkt_getuint32(pktin);
char *p;
int len;
struct ssh_channel *c;
+ c = ssh_channel_msg(ssh, pktin);
ssh_pkt_getstring(pktin, &p, &len);
- c = find234(ssh->channels, &i, ssh_channelfind);
if (c) {
int bufsize = ssh_channel_data(c, FALSE, p, len);
if (!c->throttling_conn && bufsize > SSH1_BUFFER_LIMIT) {
* Find the channel associated with a message. If there's no channel,
* or it's not properly open, make a noise about it and return NULL.
*/
-static struct ssh_channel *ssh2_channel_msg(Ssh ssh, struct Packet *pktin)
+static struct ssh_channel *ssh_channel_msg(Ssh ssh, struct Packet *pktin)
{
unsigned localid = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
+ int halfopen_ok;
+ /* Is this message OK on a half-open connection? */
+ if (ssh->version == 1)
+ halfopen_ok = (pktin->type == SSH1_MSG_CHANNEL_OPEN_CONFIRMATION ||
+ pktin->type == SSH1_MSG_CHANNEL_OPEN_FAILURE);
+ else
+ halfopen_ok = (pktin->type == SSH2_MSG_CHANNEL_OPEN_CONFIRMATION ||
+ pktin->type == SSH2_MSG_CHANNEL_OPEN_FAILURE);
c = find234(ssh->channels, &localid, ssh_channelfind);
- if (!c ||
- (c->type != CHAN_SHARING && c->halfopen &&
- pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION &&
- pktin->type != SSH2_MSG_CHANNEL_OPEN_FAILURE)) {
+ if (!c || (c->type != CHAN_SHARING && (c->halfopen != halfopen_ok))) {
char *buf = dupprintf("Received %s for %s channel %u",
- ssh2_pkt_type(ssh->pkt_kctx, ssh->pkt_actx,
- pktin->type),
- c ? "half-open" : "nonexistent", localid);
+ ssh_pkt_type(ssh, pktin->type),
+ !c ? "nonexistent" :
+ c->halfopen ? "half-open" : "open",
+ localid);
ssh_disconnect(ssh, NULL, buf, SSH2_DISCONNECT_PROTOCOL_ERROR, FALSE);
sfree(buf);
return NULL;
static void ssh2_msg_channel_response(Ssh ssh, struct Packet *pktin)
{
- struct ssh_channel *c = ssh2_channel_msg(ssh, pktin);
+ struct ssh_channel *c = ssh_channel_msg(ssh, pktin);
struct outstanding_channel_request *ocr;
if (!c) return;
static void ssh2_msg_channel_window_adjust(Ssh ssh, struct Packet *pktin)
{
struct ssh_channel *c;
- c = ssh2_channel_msg(ssh, pktin);
+ c = ssh_channel_msg(ssh, pktin);
if (!c)
return;
if (c->type == CHAN_SHARING) {
char *data;
int length;
struct ssh_channel *c;
- c = ssh2_channel_msg(ssh, pktin);
+ c = ssh_channel_msg(ssh, pktin);
if (!c)
return;
if (c->type == CHAN_SHARING) {
Ssh ssh = c->ssh;
struct Packet *pktout;
+ assert(ssh->version == 2);
if (c->halfopen) {
/*
* If we've sent out our own CHANNEL_OPEN but not yet seen
{
struct ssh_channel *c;
- c = ssh2_channel_msg(ssh, pktin);
+ c = ssh_channel_msg(ssh, pktin);
if (!c)
return;
if (c->type == CHAN_SHARING) {
{
struct ssh_channel *c;
- c = ssh2_channel_msg(ssh, pktin);
+ c = ssh_channel_msg(ssh, pktin);
if (!c)
return;
if (c->type == CHAN_SHARING) {
{
struct ssh_channel *c;
- c = ssh2_channel_msg(ssh, pktin);
+ c = ssh_channel_msg(ssh, pktin);
if (!c)
return;
if (c->type == CHAN_SHARING) {
pktin->body, pktin->length);
return;
}
- assert(c->halfopen); /* ssh2_channel_msg will have enforced this */
+ assert(c->halfopen); /* ssh_channel_msg will have enforced this */
c->remoteid = ssh_pkt_getuint32(pktin);
c->halfopen = FALSE;
c->v.v2.remwindow = ssh_pkt_getuint32(pktin);
int reason_length;
struct ssh_channel *c;
- c = ssh2_channel_msg(ssh, pktin);
+ c = ssh_channel_msg(ssh, pktin);
if (!c)
return;
if (c->type == CHAN_SHARING) {
pktin->body, pktin->length);
return;
}
- assert(c->halfopen); /* ssh2_channel_msg will have enforced this */
+ assert(c->halfopen); /* ssh_channel_msg will have enforced this */
if (c->type == CHAN_SOCKDATA_DORMANT) {
reason_code = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
struct Packet *pktout;
- c = ssh2_channel_msg(ssh, pktin);
+ c = ssh_channel_msg(ssh, pktin);
if (!c)
return;
if (c->type == CHAN_SHARING) {