*
* - SSH1_BUFFER_LIMIT is the amount of backlog that must build up
* on a local data stream before we throttle the whole SSH
- * connection (in SSH1 only). Throttling the whole connection is
+ * connection (in SSH-1 only). Throttling the whole connection is
* pretty drastic so we set this high in the hope it won't
* happen very often.
*
* - SSH_MAX_BACKLOG is the amount of backlog that must build up
* on the SSH connection itself before we defensively throttle
* _all_ local data streams. This is pretty drastic too (though
- * thankfully unlikely in SSH2 since the window mechanism should
+ * thankfully unlikely in SSH-2 since the window mechanism should
* ensure that the server never has any need to throttle its end
* of the connection), so we set this high as well.
*
- * - OUR_V2_WINSIZE is the maximum window size we present on SSH2
+ * - OUR_V2_WINSIZE is the maximum window size we present on SSH-2
* channels.
*/
/* True if we opened this channel but server hasn't confirmed. */
int halfopen;
/*
- * In SSH1, this value contains four bits:
+ * In SSH-1, this value contains four bits:
*
* 1 We have sent SSH1_MSG_CHANNEL_CLOSE.
* 2 We have sent SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION.
};
/*
- * 2-3-4 tree storing remote->local port forwardings. SSH 1 and SSH
- * 2 use this structure in different ways, reflecting SSH 2's
+ * 2-3-4 tree storing remote->local port forwardings. SSH-1 and SSH-2
+ * use this structure in different ways, reflecting SSH-2's
* altogether saner approach to port forwarding.
*
- * In SSH 1, you arrange a remote forwarding by sending the server
+ * In SSH-1, you arrange a remote forwarding by sending the server
* the remote port number, and the local destination host:port.
* When a connection comes in, the server sends you back that
* host:port pair, and you connect to it. This is a ready-made
* host:port pairs we _are_ trying to forward to, and reject a
* connection request from the server if it's not in the list.
*
- * In SSH 2, each side of the connection minds its own business and
+ * In SSH-2, each side of the connection minds its own business and
* doesn't send unnecessary information to the other. You arrange a
* remote forwarding by sending the server just the remote port
* number. When a connection comes in, the server tells you which
* of its ports was connected to; and _you_ have to remember what
* local host:port pair went with that port number.
*
- * Hence, in SSH 1 this structure is indexed by destination
- * host:port pair, whereas in SSH 2 it is indexed by source port.
+ * Hence, in SSH-1 this structure is indexed by destination
+ * host:port pair, whereas in SSH-2 it is indexed by source port.
*/
struct ssh_portfwd; /* forward declaration */
unsigned char *body;
long savedpos;
long maxlen;
- long encrypted_len; /* for SSH2 total-size counting */
+ long encrypted_len; /* for SSH-2 total-size counting */
/*
* State associated with packet logging
struct rdpkt1_state_tag rdpkt1_state;
struct rdpkt2_state_tag rdpkt2_state;
- /* ssh1 and ssh2 use this for different things, but both use it */
+ /* SSH-1 and SSH-2 use this for different things, but both use it */
int protocol_initial_phase_done;
void (*protocol) (Ssh ssh, void *vin, int inlen,
}
/*
- * SSH2 packet construction functions.
+ * SSH-2 packet construction functions.
*/
static void ssh2_pkt_ensure(struct Packet *pkt, int length)
{
}
/*
- * Construct an SSH2 final-form packet: compress it, encrypt it,
+ * Construct an SSH-2 final-form packet: compress it, encrypt it,
* put the MAC on it. Final packet, ready to be sent, is stored in
* pkt->data. Total length is returned.
*/
*/
/*
- * Send an SSH2 packet immediately, without queuing or deferring.
+ * Send an SSH-2 packet immediately, without queuing or deferring.
*/
static void ssh2_pkt_send_noqueue(Ssh ssh, struct Packet *pkt)
{
}
/*
- * Defer an SSH2 packet.
+ * Defer an SSH-2 packet.
*/
static void ssh2_pkt_defer_noqueue(Ssh ssh, struct Packet *pkt)
{
}
/*
- * Queue an SSH2 packet.
+ * Queue an SSH-2 packet.
*/
static void ssh2_pkt_queue(Ssh ssh, struct Packet *pkt)
{
/*
* Send the whole deferred data block constructed by
- * ssh2_pkt_defer() or SSH1's defer_packet().
+ * ssh2_pkt_defer() or SSH-1's defer_packet().
*
* The expected use of the defer mechanism is that you call
* ssh2_pkt_defer() a few times, then call ssh_pkt_defersend(). If
}
/*
- * Send all queued SSH2 packets. We send them by means of
+ * Send all queued SSH-2 packets. We send them by means of
* ssh2_pkt_defer_noqueue(), in case they included a pair of
* packets that needed to be lumped together.
*/
}
/*
- * Packet decode functions for both SSH1 and SSH2.
+ * Packet decode functions for both SSH-1 and SSH-2.
*/
static unsigned long ssh_pkt_getuint32(struct Packet *pkt)
{
}
/*
- * Helper function to add an SSH2 signature blob to a packet.
+ * Helper function to add an SSH-2 signature blob to a packet.
* Expects to be shown the public key blob as well as the signature
* blob. Normally works just like ssh2_pkt_addstring, but will
* fiddle with the signature packet if necessary for
* sniffing.
*/
ssh->remote_bugs |= BUG_CHOKES_ON_SSH1_IGNORE;
- logevent("We believe remote version has SSH1 ignore bug");
+ logevent("We believe remote version has SSH-1 ignore bug");
}
if (ssh->cfg.sshbug_plainpw1 == FORCE_ON ||
* the password.
*/
ssh->remote_bugs |= BUG_NEEDS_SSH1_PLAIN_PASSWORD;
- logevent("We believe remote version needs a plain SSH1 password");
+ logevent("We believe remote version needs a plain SSH-1 password");
}
if (ssh->cfg.sshbug_rsa1 == FORCE_ON ||
* an AUTH_RSA message.
*/
ssh->remote_bugs |= BUG_CHOKES_ON_RSA;
- logevent("We believe remote version can't handle RSA authentication");
+ logevent("We believe remote version can't handle SSH-1 RSA authentication");
}
if (ssh->cfg.sshbug_hmac2 == FORCE_ON ||
* These versions have the HMAC bug.
*/
ssh->remote_bugs |= BUG_SSH2_HMAC;
- logevent("We believe remote version has SSH2 HMAC bug");
+ logevent("We believe remote version has SSH-2 HMAC bug");
}
if (ssh->cfg.sshbug_derivekey2 == FORCE_ON ||
* generate the keys).
*/
ssh->remote_bugs |= BUG_SSH2_DERIVEKEY;
- logevent("We believe remote version has SSH2 key-derivation bug");
+ logevent("We believe remote version has SSH-2 key-derivation bug");
}
if (ssh->cfg.sshbug_rsapad2 == FORCE_ON ||
(wc_match("OpenSSH_2.[5-9]*", imp) ||
wc_match("OpenSSH_3.[0-2]*", imp)))) {
/*
- * These versions have the SSH2 RSA padding bug.
+ * These versions have the SSH-2 RSA padding bug.
*/
ssh->remote_bugs |= BUG_SSH2_RSA_PADDING;
- logevent("We believe remote version has SSH2 RSA padding bug");
+ logevent("We believe remote version has SSH-2 RSA padding bug");
}
if (ssh->cfg.sshbug_pksessid2 == FORCE_ON ||
(ssh->cfg.sshbug_pksessid2 == AUTO &&
wc_match("OpenSSH_2.[0-2]*", imp))) {
/*
- * These versions have the SSH2 session-ID bug in
+ * These versions have the SSH-2 session-ID bug in
* public-key authentication.
*/
ssh->remote_bugs |= BUG_SSH2_PK_SESSIONID;
- logevent("We believe remote version has SSH2 public-key-session-ID bug");
+ logevent("We believe remote version has SSH-2 public-key-session-ID bug");
}
if (ssh->cfg.sshbug_rekey2 == FORCE_ON ||
wc_match("Sun_SSH_1.0", imp) ||
wc_match("Sun_SSH_1.0.1", imp)))) {
/*
- * These versions have the SSH2 rekey bug.
+ * These versions have the SSH-2 rekey bug.
*/
ssh->remote_bugs |= BUG_SSH2_REKEY;
- logevent("We believe remote version has SSH2 rekey bug");
+ logevent("We believe remote version has SSH-2 rekey bug");
}
}
strcspn(s->vstring, "\015\012"));
/*
- * Initialise SSHv2 protocol.
+ * Initialise SSH-2 protocol.
*/
ssh->protocol = ssh2_protocol;
ssh2_protocol_setup(ssh);
ssh->s_rdpkt = ssh2_rdpkt;
} else {
/*
- * Initialise SSHv1 protocol.
+ * Initialise SSH-1 protocol.
*/
ssh->protocol = ssh1_protocol;
ssh1_protocol_setup(ssh);
static void ssh_set_frozen(Ssh ssh, int frozen)
{
- sk_set_frozen(ssh->s, frozen);
+ if (ssh->s)
+ sk_set_frozen(ssh->s, frozen);
ssh->frozen = frozen;
}
error_msg = "Server unexpectedly closed network connection";
}
+ if (need_notify)
+ notify_remote_exit(ssh->frontend);
+
if (error_msg) {
/* A socket error has occurred. */
logevent(error_msg);
} else {
logevent("Server closed network connection");
}
- if (need_notify)
- notify_remote_exit(ssh->frontend);
return 0;
}
/*
* Username and password input, abstracted off into routines
- * reusable in several places - even between SSH1 and SSH2.
+ * reusable in several places - even between SSH-1 and SSH-2.
*/
/* Set up a username or password input loop on a given buffer. */
ptr = ssh_pkt_getdata(pktin, 8);
if (!ptr) {
- bombout(("SSH1 public key packet stopped before random cookie"));
+ bombout(("SSH-1 public key packet stopped before random cookie"));
crStop(0);
}
memcpy(cookie, ptr, 8);
if (!ssh1_pkt_getrsakey(pktin, &servkey, &s->keystr1) ||
!ssh1_pkt_getrsakey(pktin, &hostkey, &s->keystr2)) {
- bombout(("Failed to read SSH1 public keys from public key packet"));
+ bombout(("Failed to read SSH-1 public keys from public key packet"));
crStop(0);
}
*/
if (hostkey.bits > hostkey.bytes * 8 ||
servkey.bits > servkey.bytes * 8) {
- bombout(("SSH1 public keys were badly formatted"));
+ bombout(("SSH-1 public keys were badly formatted"));
crStop(0);
}
if (s->dlgret == 0) {
ssh->close_expected = TRUE;
ssh_closing((Plug)ssh, NULL, 0, 0);
+ crStop(0);
}
}
ret = rsaencrypt(s->rsabuf, hostkey.bytes, &servkey);
}
if (!ret) {
- bombout(("SSH1 public key encryptions failed due to bad formatting"));
+ bombout(("SSH-1 public key encryptions failed due to bad formatting"));
crStop(0);
}
warn = 1;
} else if (next_cipher == CIPHER_AES) {
/* XXX Probably don't need to mention this. */
- logevent("AES not supported in SSH1, skipping");
+ logevent("AES not supported in SSH-1, skipping");
} else {
switch (next_cipher) {
case CIPHER_3DES: s->cipher_type = SSH_CIPHER_3DES;
}
if (!cipher_chosen) {
if ((s->supported_ciphers_mask & (1 << SSH_CIPHER_3DES)) == 0)
- bombout(("Server violates SSH 1 protocol by not "
+ bombout(("Server violates SSH-1 protocol by not "
"supporting 3DES encryption"));
else
/* shouldn't happen */
if (s->dlgret == 0) {
ssh->close_expected = TRUE;
ssh_closing((Plug)ssh, NULL, 0, 0);
+ crStop(0);
}
}
}
s->p = s->response + 5;
s->nkeys = GET_32BIT(s->p);
s->p += 4;
- logeventf(ssh, "Pageant has %d SSH1 keys", s->nkeys);
+ logeventf(ssh, "Pageant has %d SSH-1 keys", s->nkeys);
for (s->keyi = 0; s->keyi < s->nkeys; s->keyi++) {
logeventf(ssh, "Trying Pageant key #%d", s->keyi);
if (s->publickey_blob &&
bombout(("TIS challenge packet was badly formed"));
crStop(0);
}
+ c_write_str(ssh, "Using TIS authentication.\r\n");
logevent("Received TIS challenge");
if (challengelen > sizeof(s->prompt) - 1)
challengelen = sizeof(s->prompt) - 1;/* prevent overrun */
bombout(("CryptoCard challenge packet was badly formed"));
crStop(0);
}
+ c_write_str(ssh, "Using CryptoCard authentication.\r\n");
logevent("Received CryptoCard challenge");
if (challengelen > sizeof(s->prompt) - 1)
challengelen = sizeof(s->prompt) - 1;/* prevent overrun */
{
Ssh ssh = c->ssh;
- if (ssh->state != SSH_STATE_SESSION) {
- assert(ssh->state == SSH_STATE_CLOSED);
+ if (ssh->state == SSH_STATE_CLOSED)
return;
- }
if (c && !c->closes) {
/*
{
Ssh ssh = c->ssh;
- if (ssh->state != SSH_STATE_SESSION) {
- assert(ssh->state == SSH_STATE_CLOSED);
+ if (ssh->state == SSH_STATE_CLOSED)
return 0;
- }
if (ssh->version == 1) {
send_packet(ssh, SSH1_MSG_CHANNEL_DATA,
PKT_INT, len, PKT_DATA, buf, len,
PKTT_OTHER, PKT_END);
/*
- * In SSH1 we can return 0 here - implying that forwarded
+ * In SSH-1 we can return 0 here - implying that forwarded
* connections are never individually throttled - because
* the only circumstance that can cause throttling will be
* the whole SSH connection backing up, in which case
{
Ssh ssh = c->ssh;
- if (ssh->state != SSH_STATE_SESSION) {
- assert(ssh->state == SSH_STATE_CLOSED);
+ if (ssh->state == SSH_STATE_CLOSED)
return;
- }
if (ssh->version == 1) {
if (c->v.v1.throttling && bufsize < SSH1_BUFFER_LIMIT) {
portfwd_strptr++;
sports[n] = '\0';
if (ssh->version == 1 && type == 'R') {
- logeventf(ssh, "SSH1 cannot handle remote source address "
+ logeventf(ssh, "SSH-1 cannot handle remote source address "
"spec \"%s\"; ignoring", sports);
} else
strcpy(saddr, sports);
n = 0;
}
- if (n < 255) sports[n++] = *portfwd_strptr++;
+ if (n < lenof(sports)-1) sports[n++] = *portfwd_strptr++;
}
sports[n] = 0;
if (type != 'D') {
portfwd_strptr++;
n = 0;
while (*portfwd_strptr && *portfwd_strptr != ':') {
- if (n < 255) host[n++] = *portfwd_strptr++;
+ if (n < lenof(host)-1) host[n++] = *portfwd_strptr++;
}
host[n] = 0;
if (*portfwd_strptr == ':')
portfwd_strptr++;
n = 0;
while (*portfwd_strptr) {
- if (n < 255) dports[n++] = *portfwd_strptr++;
+ if (n < lenof(dports)-1) dports[n++] = *portfwd_strptr++;
}
dports[n] = 0;
portfwd_strptr++;
if (ssh->version == 1) {
/*
* We cannot cancel listening ports on the
- * server side in SSH1! There's no message
+ * server side in SSH-1! There's no message
* to support it. Instead, we simply remove
* the rportfwd record from the local end
* so that any connections the server tries
/*
* Start the shell or command.
*
- * Special case: if the first-choice command is an SSH2
+ * Special case: if the first-choice command is an SSH-2
* subsystem (hence not usable here) and the second choice
* exists, we fall straight back to that.
*/
{
char *cmd = ssh->cfg.remote_cmd_ptr;
+
+ if (!cmd) cmd = ssh->cfg.remote_cmd;
if (ssh->cfg.ssh_subsys && ssh->cfg.remote_cmd_ptr2) {
cmd = ssh->cfg.remote_cmd_ptr2;
}
/*
- * Handle the top-level SSH2 protocol.
+ * Handle the top-level SSH-2 protocol.
*/
static void ssh1_msg_debug(Ssh ssh, struct Packet *pktin)
{
/*
- * SSH2 key creation method.
+ * SSH-2 key creation method.
*/
static void ssh2_mkkey(Ssh ssh, Bignum K, unsigned char *H,
unsigned char *sessid, char chr,
}
/*
- * Handle the SSH2 transport layer.
+ * Handle the SSH-2 transport layer.
*/
static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
struct Packet *pktin)
if (s->dlgret == 0) {
ssh->close_expected = TRUE;
ssh_closing((Plug)ssh, NULL, 0, 0);
+ crStop(0);
}
}
if (s->dlgret == 0) {
ssh->close_expected = TRUE;
ssh_closing((Plug)ssh, NULL, 0, 0);
+ crStop(0);
}
}
if (s->dlgret == 0) {
ssh->close_expected = TRUE;
ssh_closing((Plug)ssh, NULL, 0, 0);
+ crStop(0);
}
}
}
/*
- * Add data to an SSH2 channel output buffer.
+ * Add data to an SSH-2 channel output buffer.
*/
static void ssh2_add_channel_data(struct ssh_channel *c, char *buf,
int len)
}
/*
- * Attempt to send data on an SSH2 channel.
+ * Attempt to send data on an SSH-2 channel.
*/
static int ssh2_try_send(struct ssh_channel *c)
{
}
/*
- * Potentially enlarge the window on an SSH2 channel.
+ * Potentially enlarge the window on an SSH-2 channel.
*/
static void ssh2_set_window(struct ssh_channel *c, unsigned newwin)
{
/*
* We used to send SSH_MSG_DISCONNECT here,
* because I'd believed that _every_ conforming
- * SSH2 connection had to end with a disconnect
+ * SSH-2 connection had to end with a disconnect
* being sent by at least one side; apparently
* I was wrong and it's perfectly OK to
* unceremoniously slam the connection shut
}
/*
- * Handle the SSH2 userauth and connection layers.
+ * Handle the SSH-2 userauth and connection layers.
*/
static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin)
s->p = s->response + 5;
s->nkeys = GET_32BIT(s->p);
s->p += 4;
- logeventf(ssh, "Pageant has %d SSH2 keys", s->nkeys);
+ logeventf(ssh, "Pageant has %d SSH-2 keys", s->nkeys);
for (s->keyi = 0; s->keyi < s->nkeys; s->keyi++) {
void *vret;
continue;
}
+ c_write_str(ssh, "Using keyboard-interactive authentication.\r\n");
s->kbd_inter_running = TRUE;
s->curr_prompt = 0;
}
} else {
subsys = ssh->cfg.ssh_subsys;
cmd = ssh->cfg.remote_cmd_ptr;
+ if (!cmd) cmd = ssh->cfg.remote_cmd;
}
s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
}
/*
- * Handlers for SSH2 messages that might arrive at any moment.
+ * Handlers for SSH-2 messages that might arrive at any moment.
*/
static void ssh2_msg_disconnect(Ssh ssh, struct Packet *pktin)
{
}
/*
- * Handle the top-level SSH2 protocol.
+ * Handle the top-level SSH-2 protocol.
*/
static void ssh2_protocol_setup(Ssh ssh)
{
* These special message types we install handlers for.
*/
ssh->packet_dispatch[SSH2_MSG_DISCONNECT] = ssh2_msg_disconnect;
- ssh->packet_dispatch[SSH2_MSG_IGNORE] = ssh_msg_ignore; /* shared with ssh1 */
+ ssh->packet_dispatch[SSH2_MSG_IGNORE] = ssh_msg_ignore; /* shared with SSH-1 */
ssh->packet_dispatch[SSH2_MSG_DEBUG] = ssh2_msg_debug;
}
if (ssh->state == SSH_STATE_CLOSED
|| ssh->state == SSH_STATE_PREPACKET) return;
if (ssh->version == 1) {
- logevent("Unable to send BREAK signal in SSH1");
+ logevent("Unable to send BREAK signal in SSH-1");
} else if (ssh->mainchan) {
pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(pktout, ssh->mainchan->remoteid);