#include "putty.h"
#include "tree234.h"
#include "ssh.h"
+#include "sshgss.h"
#ifndef FALSE
#define FALSE 0
#define SSH2_MSG_CHANNEL_REQUEST 98 /* 0x62 */
#define SSH2_MSG_CHANNEL_SUCCESS 99 /* 0x63 */
#define SSH2_MSG_CHANNEL_FAILURE 100 /* 0x64 */
+#define SSH2_MSG_USERAUTH_GSSAPI_RESPONSE 60
+#define SSH2_MSG_USERAUTH_GSSAPI_TOKEN 61
+#define SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE 63
+#define SSH2_MSG_USERAUTH_GSSAPI_ERROR 64
+#define SSH2_MSG_USERAUTH_GSSAPI_ERRTOK 65
+#define SSH2_MSG_USERAUTH_GSSAPI_MIC 66
/*
* Packet type contexts, so that ssh2_pkt_type can correctly decode
SSH2_PKTCTX_NOAUTH,
SSH2_PKTCTX_PUBLICKEY,
SSH2_PKTCTX_PASSWORD,
+ SSH2_PKTCTX_GSSAPI,
SSH2_PKTCTX_KBDINTER
} Pkt_ACtx;
#define BUG_SSH2_DERIVEKEY 32
#define BUG_SSH2_REKEY 64
#define BUG_SSH2_PK_SESSIONID 128
+#define BUG_SSH2_MAXPKT 256
/*
* Codes for terminal modes.
}
static char *ssh2_pkt_type(Pkt_KCtx pkt_kctx, Pkt_ACtx pkt_actx, int type)
{
+ translatea(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,SSH2_PKTCTX_GSSAPI);
+ translatea(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,SSH2_PKTCTX_GSSAPI);
+ translatea(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,SSH2_PKTCTX_GSSAPI);
+ translatea(SSH2_MSG_USERAUTH_GSSAPI_ERROR,SSH2_PKTCTX_GSSAPI);
+ translatea(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,SSH2_PKTCTX_GSSAPI);
+ translatea(SSH2_MSG_USERAUTH_GSSAPI_MIC, SSH2_PKTCTX_GSSAPI);
translate(SSH2_MSG_DISCONNECT);
translate(SSH2_MSG_IGNORE);
translate(SSH2_MSG_UNIMPLEMENTED);
int kex_in_progress;
long next_rekey, last_rekey;
char *deferred_rekey_reason; /* points to STATIC string; don't free */
+
+ /*
+ * Fully qualified host name, which we need if doing GSSAPI.
+ */
+ char *fullhostname;
};
#define logevent(s) logevent(ssh->frontend, s)
PKT_INCOMING, st->pktin->type,
ssh1_pkt_type(st->pktin->type),
st->pktin->body, st->pktin->length,
- nblanks, &blank);
+ nblanks, &blank, NULL);
}
crFinish(st->pktin);
ssh2_pkt_type(ssh->pkt_kctx, ssh->pkt_actx,
st->pktin->type),
st->pktin->data+6, st->pktin->length-6,
- nblanks, &blank);
+ nblanks, &blank, &st->pktin->sequence);
}
crFinish(st->pktin);
log_packet(ssh->logctx, PKT_OUTGOING, pkt->data[12],
ssh1_pkt_type(pkt->data[12]),
pkt->body, pkt->length - (pkt->body - pkt->data),
- pkt->nblanks, pkt->blanks);
+ pkt->nblanks, pkt->blanks, NULL);
sfree(pkt->blanks); pkt->blanks = NULL;
pkt->nblanks = 0;
static int s_write(Ssh ssh, void *data, int len)
{
if (ssh->logctx)
- log_packet(ssh->logctx, PKT_OUTGOING, -1, NULL, data, len, 0, NULL);
+ log_packet(ssh->logctx, PKT_OUTGOING, -1, NULL, data, len,
+ 0, NULL, NULL);
return sk_write(ssh->s, (char *)data, len);
}
log_packet(ssh->logctx, PKT_OUTGOING, pkt->data[5],
ssh2_pkt_type(ssh->pkt_kctx, ssh->pkt_actx, pkt->data[5]),
pkt->body, pkt->length - (pkt->body - pkt->data),
- pkt->nblanks, pkt->blanks);
+ pkt->nblanks, pkt->blanks, &ssh->v2_outgoing_sequence);
sfree(pkt->blanks); pkt->blanks = NULL;
pkt->nblanks = 0;
ssh->remote_bugs |= BUG_SSH2_REKEY;
logevent("We believe remote version has SSH-2 rekey bug");
}
+
+ if (ssh->cfg.sshbug_maxpkt2 == FORCE_ON ||
+ (ssh->cfg.sshbug_maxpkt2 == AUTO &&
+ (wc_match("1.36_sshlib GlobalSCAPE", imp) ||
+ wc_match("1.36 sshlib: GlobalScape", imp)))) {
+ /*
+ * This version ignores our makpkt and needs to be throttled.
+ */
+ ssh->remote_bugs |= BUG_SSH2_MAXPKT;
+ logevent("We believe remote version ignores SSH-2 maximum packet size");
+ }
}
/*
/* Log raw data, if we're in that mode. */
if (ssh->logctx)
log_packet(ssh->logctx, PKT_INCOMING, -1, NULL, data, datalen,
- 0, NULL);
+ 0, NULL, NULL);
crBegin(ssh->ssh_gotdata_crstate);
SockAddr addr;
const char *err;
- ssh->savedhost = snewn(1 + strlen(host), char);
- strcpy(ssh->savedhost, host);
+ if (*ssh->cfg.loghost) {
+ char *colon;
- if (port < 0)
- port = 22; /* default ssh port */
- ssh->savedport = port;
+ ssh->savedhost = dupstr(ssh->cfg.loghost);
+ ssh->savedport = 22; /* default ssh port */
+
+ /*
+ * A colon suffix on savedhost also lets us affect
+ * savedport.
+ *
+ * (FIXME: do something about IPv6 address literals here.)
+ */
+ colon = strrchr(ssh->savedhost, ':');
+ if (colon) {
+ *colon++ = '\0';
+ if (*colon)
+ ssh->savedport = atoi(colon);
+ }
+ } else {
+ ssh->savedhost = dupstr(host);
+ if (port < 0)
+ port = 22; /* default ssh port */
+ ssh->savedport = port;
+ }
/*
* Try to find host.
sk_addr_free(addr);
return err;
}
+ ssh->fullhostname = dupstr(*realhost); /* save in case of GSSAPI */
/*
* Open socket.
ssh_send_verstring(ssh, NULL);
}
+ /*
+ * loghost, if configured, overrides realhost.
+ */
+ if (*ssh->cfg.loghost) {
+ sfree(*realhost);
+ *realhost = dupstr(ssh->cfg.loghost);
+ }
+
return NULL;
}
}
/*
+ * Set up most of a new ssh_channel for SSH-2.
+ */
+static void ssh2_channel_init(struct ssh_channel *c)
+{
+ Ssh ssh = c->ssh;
+ c->localid = alloc_channel_id(ssh);
+ c->closes = 0;
+ c->throttling_conn = FALSE;
+ c->v.v2.locwindow = c->v.v2.locmaxwin = c->v.v2.remlocwin =
+ ssh->cfg.ssh_simple ? OUR_V2_BIGWIN : OUR_V2_WINSIZE;
+ c->v.v2.winadj_head = c->v.v2.winadj_tail = NULL;
+ c->v.v2.throttle_state = UNTHROTTLED;
+ bufchain_init(&c->v.v2.outbuffer);
+}
+
+/*
* Potentially enlarge the window on an SSH-2 channel.
*/
static void ssh2_set_window(struct ssh_channel *c, int newwin)
return;
/*
+ * If the remote end has a habit of ignoring maxpkt, limit the
+ * window so that it has no choice (assuming it doesn't ignore the
+ * window as well).
+ */
+ if ((ssh->remote_bugs & BUG_SSH2_MAXPKT) && newwin > OUR_V2_MAXPKT)
+ newwin = OUR_V2_MAXPKT;
+
+
+ /*
* Only send a WINDOW_ADJUST if there's significantly more window
* available than the other end thinks there is. This saves us
* sending a WINDOW_ADJUST for every character in a shell session.
int msglen = 0, core = FALSE;
/* ICK: older versions of OpenSSH (e.g. 3.4p1)
* provide an `int' for the signal, despite its
- * having been a `string' in the drafts since at
+ * having been a `string' in the drafts of RFC 4254 since at
* least 2001. (Fixed in session.c 1.147.) Try to
* infer which we can safely parse it as. */
{
fmt_sig = dupprintf(" %d", signum);
ssh->exitcode = 128 + signum;
} else {
- /* As per the drafts. */
+ /* As per RFC 4254. */
char *sig;
int siglen;
ssh_pkt_getstring(pktin, &sig, &siglen);
logeventf(ssh, "Rejected channel open: %s", error);
sfree(c);
} else {
- c->localid = alloc_channel_id(ssh);
- c->closes = 0;
- c->throttling_conn = FALSE;
- c->v.v2.locwindow = c->v.v2.locmaxwin = OUR_V2_WINSIZE;
+ ssh2_channel_init(c);
c->v.v2.remwindow = winsize;
c->v.v2.remmaxpkt = pktsize;
- c->v.v2.remlocwin = OUR_V2_WINSIZE;
- c->v.v2.winadj_head = c->v.v2.winadj_tail = NULL;
- c->v.v2.throttle_state = UNTHROTTLED;
- bufchain_init(&c->v.v2.outbuffer);
add234(ssh->channels, c);
pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
ssh2_pkt_adduint32(pktout, c->remoteid);
AUTH_TYPE_PUBLICKEY_OFFER_LOUD,
AUTH_TYPE_PUBLICKEY_OFFER_QUIET,
AUTH_TYPE_PASSWORD,
+ AUTH_TYPE_GSSAPI,
AUTH_TYPE_KEYBOARD_INTERACTIVE,
AUTH_TYPE_KEYBOARD_INTERACTIVE_QUIET
} type;
int done_service_req;
int gotit, need_pw, can_pubkey, can_passwd, can_keyb_inter;
int tried_pubkey_config, done_agent;
+ int can_gssapi;
+ int tried_gssapi;
int kbd_inter_refused;
int we_are_in;
prompts_t *cur_prompt;
int try_send;
int num_env, env_left, env_ok;
struct Packet *pktout;
+ Ssh_gss_ctx gss_ctx;
+ Ssh_gss_buf gss_buf;
+ Ssh_gss_buf gss_rcvtok, gss_sndtok;
+ Ssh_gss_name gss_srv_name;
+ Ssh_gss_stat gss_stat;
};
crState(do_ssh2_authconn_state);
s->done_service_req = FALSE;
s->we_are_in = FALSE;
+ s->tried_gssapi = FALSE;
+
if (!ssh->cfg.ssh_no_userauth) {
/*
* Request userauth protocol, and await a response to it.
break;
}
- if (pktin->type != SSH2_MSG_USERAUTH_FAILURE) {
+ if (pktin->type != SSH2_MSG_USERAUTH_FAILURE && s->type != AUTH_TYPE_GSSAPI) {
bombout(("Strange packet received during authentication: "
"type %d", pktin->type));
crStopV;
in_commasep_string("password", methods, methlen);
s->can_keyb_inter = ssh->cfg.try_ki_auth &&
in_commasep_string("keyboard-interactive", methods, methlen);
+#ifndef NO_GSSAPI
+ s->can_gssapi = ssh->cfg.try_gssapi_auth &&
+ in_commasep_string("gssapi-with-mic", methods, methlen) &&
+ ssh_gss_init();
+#endif
}
ssh->pkt_actx = SSH2_PKTCTX_NOAUTH;
key->alg->freekey(key->data);
}
+#ifndef NO_GSSAPI
+ } else if (s->can_gssapi && !s->tried_gssapi) {
+
+ /* GSSAPI Authentication */
+
+ int micoffset;
+ Ssh_gss_buf mic;
+ s->type = AUTH_TYPE_GSSAPI;
+ s->tried_gssapi = TRUE;
+ s->gotit = TRUE;
+ ssh->pkt_actx = SSH2_PKTCTX_GSSAPI;
+
+ /* Sending USERAUTH_REQUEST with "gssapi-with-mic" method */
+ s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
+ ssh2_pkt_addstring(s->pktout, s->username);
+ ssh2_pkt_addstring(s->pktout, "ssh-connection");
+ ssh2_pkt_addstring(s->pktout, "gssapi-with-mic");
+
+ /* add mechanism info */
+ ssh_gss_indicate_mech(&s->gss_buf);
+
+ /* number of GSSAPI mechanisms */
+ ssh2_pkt_adduint32(s->pktout,1);
+
+ /* length of OID + 2 */
+ ssh2_pkt_adduint32(s->pktout, s->gss_buf.len + 2);
+ ssh2_pkt_addbyte(s->pktout, SSH2_GSS_OIDTYPE);
+
+ /* length of OID */
+ ssh2_pkt_addbyte(s->pktout, (unsigned char) s->gss_buf.len);
+
+ ssh_pkt_adddata(s->pktout, s->gss_buf.data, s->gss_buf.len);
+ ssh2_pkt_send(ssh, s->pktout);
+ crWaitUntilV(pktin);
+ if (pktin->type != SSH2_MSG_USERAUTH_GSSAPI_RESPONSE) {
+ logevent("GSSAPI authentication request refused");
+ continue;
+ }
+
+ /* check returned packet ... */
+
+ ssh_pkt_getstring(pktin,&s->gss_rcvtok.data,&s->gss_rcvtok.len);
+ if (s->gss_rcvtok.len != s->gss_buf.len + 2 ||
+ s->gss_rcvtok.data[0] != SSH2_GSS_OIDTYPE ||
+ s->gss_rcvtok.data[1] != s->gss_buf.len ||
+ memcmp(s->gss_rcvtok.data+2,s->gss_buf.data,s->gss_buf.len) ) {
+ logevent("GSSAPI authentication - wrong response from server");
+ continue;
+ }
+
+ /* now start running */
+ s->gss_stat = ssh_gss_import_name(ssh->fullhostname,
+ &s->gss_srv_name);
+ if (s->gss_stat != SSH_GSS_OK) {
+ if (s->gss_stat == SSH_GSS_BAD_HOST_NAME)
+ logevent("GSSAPI import name failed - Bad service name");
+ else
+ logevent("GSSAPI import name failed");
+ continue;
+ }
+
+ /* fetch TGT into GSS engine */
+ s->gss_stat = ssh_gss_acquire_cred(&s->gss_ctx);
+
+ if (s->gss_stat != SSH_GSS_OK) {
+ logevent("GSSAPI authentication failed to get credentials");
+ ssh_gss_release_name(&s->gss_srv_name);
+ continue;
+ }
+
+ /* initial tokens are empty */
+ s->gss_rcvtok.len = s->gss_sndtok.len = 0;
+ s->gss_rcvtok.data = s->gss_sndtok.data = NULL;
+
+ /* now enter the loop */
+ do {
+ s->gss_stat = ssh_gss_init_sec_context(&s->gss_ctx,
+ s->gss_srv_name,
+ ssh->cfg.gssapifwd,
+ &s->gss_rcvtok,
+ &s->gss_sndtok);
+
+ if (s->gss_stat!=SSH_GSS_S_COMPLETE &&
+ s->gss_stat!=SSH_GSS_S_CONTINUE_NEEDED) {
+ logevent("GSSAPI authentication initialisation failed");
+
+ if (ssh_gss_display_status(s->gss_ctx,&s->gss_buf) == SSH_GSS_OK) {
+ logevent(s->gss_buf.data);
+ sfree(s->gss_buf.data);
+ }
+
+ break;
+ }
+ logevent("GSSAPI authentication initialised");
+
+ /* Client and server now exchange tokens until GSSAPI
+ * no longer says CONTINUE_NEEDED */
+
+ if (s->gss_sndtok.len != 0) {
+ s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
+ ssh_pkt_addstring_start(s->pktout);
+ ssh_pkt_addstring_data(s->pktout,s->gss_sndtok.data,s->gss_sndtok.len);
+ ssh2_pkt_send(ssh, s->pktout);
+ ssh_gss_free_tok(&s->gss_sndtok);
+ }
+
+ if (s->gss_stat == SSH_GSS_S_CONTINUE_NEEDED) {
+ crWaitUntilV(pktin);
+ if (pktin->type != SSH2_MSG_USERAUTH_GSSAPI_TOKEN) {
+ logevent("GSSAPI authentication - bad server response");
+ s->gss_stat = SSH_GSS_FAILURE;
+ break;
+ }
+ ssh_pkt_getstring(pktin,&s->gss_rcvtok.data,&s->gss_rcvtok.len);
+ }
+ } while (s-> gss_stat == SSH_GSS_S_CONTINUE_NEEDED);
+
+ if (s->gss_stat != SSH_GSS_OK) {
+ ssh_gss_release_name(&s->gss_srv_name);
+ ssh_gss_release_cred(&s->gss_ctx);
+ continue;
+ }
+ logevent("GSSAPI authentication loop finished OK");
+
+ /* Now send the MIC */
+
+ s->pktout = ssh2_pkt_init(0);
+ micoffset = s->pktout->length;
+ ssh_pkt_addstring_start(s->pktout);
+ ssh_pkt_addstring_data(s->pktout, (char *)ssh->v2_session_id, ssh->v2_session_id_len);
+ ssh_pkt_addbyte(s->pktout, SSH2_MSG_USERAUTH_REQUEST);
+ ssh_pkt_addstring(s->pktout, s->username);
+ ssh_pkt_addstring(s->pktout, "ssh-connection");
+ ssh_pkt_addstring(s->pktout, "gssapi-with-mic");
+
+ s->gss_buf.data = (char *)s->pktout->data + micoffset;
+ s->gss_buf.len = s->pktout->length - micoffset;
+
+ ssh_gss_get_mic(s->gss_ctx, &s->gss_buf, &mic);
+ s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_GSSAPI_MIC);
+ ssh_pkt_addstring_start(s->pktout);
+ ssh_pkt_addstring_data(s->pktout, mic.data, mic.len);
+ ssh2_pkt_send(ssh, s->pktout);
+ ssh_gss_free_mic(&mic);
+
+ s->gotit = FALSE;
+
+ ssh_gss_release_name(&s->gss_srv_name);
+ ssh_gss_release_cred(&s->gss_ctx);
+ continue;
+#endif
} else if (s->can_keyb_inter && !s->kbd_inter_refused) {
/*
s->cur_prompt->instr_reqd = TRUE;
/*
- * Get the prompts from the packet.
+ * Get any prompt(s) from the packet.
*/
s->num_prompts = ssh_pkt_getuint32(pktin);
for (i = 0; i < s->num_prompts; i++) {
}
/*
- * Get the user's responses.
+ * Display any instructions, and get the user's
+ * response(s).
*/
- if (s->num_prompts) {
+ {
int ret; /* not live over crReturn */
ret = get_userpass_input(s->cur_prompt, NULL, 0);
while (ret < 0) {
}
/*
- * Send the responses to the server.
+ * Send the response(s) to the server.
*/
s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_INFO_RESPONSE);
ssh2_pkt_adduint32(s->pktout, s->num_prompts);
*/
ssh->mainchan = snew(struct ssh_channel);
ssh->mainchan->ssh = ssh;
- ssh->mainchan->localid = alloc_channel_id(ssh);
+ ssh2_channel_init(ssh->mainchan);
logeventf(ssh,
"Opening direct-tcpip channel to %s:%d in place of session",
ssh->cfg.ssh_nc_host, ssh->cfg.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);
- ssh->mainchan->throttling_conn = FALSE;
- ssh->mainchan->v.v2.locwindow = ssh->mainchan->v.v2.locmaxwin =
- ssh->mainchan->v.v2.remlocwin =
- ssh->cfg.ssh_simple ? OUR_V2_BIGWIN : OUR_V2_WINSIZE;
- ssh->mainchan->v.v2.winadj_head = NULL;
- ssh->mainchan->v.v2.winadj_tail = NULL;
- ssh->mainchan->v.v2.throttle_state = UNTHROTTLED;
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, ssh->cfg.ssh_nc_host);
ssh->mainchan->remoteid = ssh_pkt_getuint32(pktin);
ssh->mainchan->halfopen = FALSE;
ssh->mainchan->type = CHAN_MAINSESSION;
- ssh->mainchan->closes = 0;
ssh->mainchan->v.v2.remwindow = ssh_pkt_getuint32(pktin);
ssh->mainchan->v.v2.remmaxpkt = ssh_pkt_getuint32(pktin);
- bufchain_init(&ssh->mainchan->v.v2.outbuffer);
add234(ssh->channels, ssh->mainchan);
update_specials_menu(ssh->frontend);
logevent("Opened direct-tcpip channel");
} else {
ssh->mainchan = snew(struct ssh_channel);
ssh->mainchan->ssh = ssh;
- ssh->mainchan->localid = alloc_channel_id(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);
- ssh->mainchan->throttling_conn = FALSE;
- ssh->mainchan->v.v2.locwindow = ssh->mainchan->v.v2.locmaxwin =
- ssh->mainchan->v.v2.remlocwin =
- ssh->cfg.ssh_simple ? OUR_V2_BIGWIN : OUR_V2_WINSIZE;
- ssh->mainchan->v.v2.winadj_head = NULL;
- ssh->mainchan->v.v2.winadj_tail = NULL;
- ssh->mainchan->v.v2.throttle_state = UNTHROTTLED;
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);
ssh->mainchan->remoteid = ssh_pkt_getuint32(pktin);
ssh->mainchan->halfopen = FALSE;
ssh->mainchan->type = CHAN_MAINSESSION;
- ssh->mainchan->closes = 0;
ssh->mainchan->v.v2.remwindow = ssh_pkt_getuint32(pktin);
ssh->mainchan->v.v2.remmaxpkt = ssh_pkt_getuint32(pktin);
- bufchain_init(&ssh->mainchan->v.v2.outbuffer);
add234(ssh->channels, ssh->mainchan);
update_specials_menu(ssh->frontend);
logevent("Opened channel for session");
{
/* log reason code in disconnect message */
char *buf, *msg;
- int nowlen, reason, msglen;
+ int reason, msglen;
reason = ssh_pkt_getuint32(pktin);
ssh_pkt_getstring(pktin, &msg, &msglen);
}
logevent(buf);
sfree(buf);
- buf = dupprintf("Disconnection message text: %n%.*s",
- &nowlen, msglen, msg);
+ buf = dupprintf("Disconnection message text: %.*s",
+ msglen, msg);
logevent(buf);
- bombout(("Server sent disconnect message\ntype %d (%s):\n\"%s\"",
+ bombout(("Server sent disconnect message\ntype %d (%s):\n\"%.*s\"",
reason,
(reason > 0 && reason < lenof(ssh2_disconnect_reasons)) ?
ssh2_disconnect_reasons[reason] : "unknown",
- buf+nowlen));
+ msglen, msg));
sfree(buf);
}
sfree(ssh->do_ssh2_authconn_state);
sfree(ssh->v_c);
sfree(ssh->v_s);
+ sfree(ssh->fullhostname);
if (ssh->crcda_ctx) {
crcda_free_context(ssh->crcda_ctx);
ssh->crcda_ctx = NULL;
static const struct telnet_special ssh2_session_specials[] = {
{NULL, TS_SEP},
{"Break", TS_BRK},
- /* These are the signal names defined by draft-ietf-secsh-connect-23.
+ /* These are the signal names defined by RFC 4254.
* They include all the ISO C signals, but are a subset of the POSIX
* required signals. */
{"SIGINT (Interrupt)", TS_SIGINT},
Ssh ssh = (Ssh) handle;
struct ssh_channel *c;
c = snew(struct ssh_channel);
- c->ssh = ssh;
- if (c) {
- c->halfopen = TRUE;
- c->localid = alloc_channel_id(ssh);
- c->closes = 0;
- c->type = CHAN_SOCKDATA_DORMANT;/* identify channel type */
- c->u.pfd.s = s;
- bufchain_init(&c->v.v2.outbuffer);
- add234(ssh->channels, c);
- }
+ c->ssh = ssh;
+ ssh2_channel_init(c);
+ c->halfopen = TRUE;
+ c->type = CHAN_SOCKDATA_DORMANT;/* identify channel type */
+ c->u.pfd.s = s;
+ add234(ssh->channels, c);
return c;
}
pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
ssh2_pkt_addstring(pktout, "direct-tcpip");
ssh2_pkt_adduint32(pktout, c->localid);
- c->throttling_conn = FALSE;
- c->v.v2.locwindow = c->v.v2.locmaxwin = OUR_V2_WINSIZE;
- c->v.v2.remlocwin = OUR_V2_WINSIZE;
- c->v.v2.winadj_head = c->v.v2.winadj_head = NULL;
- c->v.v2.throttle_state = UNTHROTTLED;
ssh2_pkt_adduint32(pktout, c->v.v2.locwindow);/* our window size */
ssh2_pkt_adduint32(pktout, OUR_V2_MAXPKT); /* our max pkt size */
ssh2_pkt_addstring(pktout, hostname);