#define SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9 /* 0x9 */
#define SSH2_DISCONNECT_CONNECTION_LOST 10 /* 0xa */
#define SSH2_DISCONNECT_BY_APPLICATION 11 /* 0xb */
+#define SSH2_DISCONNECT_TOO_MANY_CONNECTIONS 12 /* 0xc */
+#define SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER 13 /* 0xd */
+#define SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14 /* 0xe */
+#define SSH2_DISCONNECT_ILLEGAL_USER_NAME 15 /* 0xf */
+
+static const char *const ssh2_disconnect_reasons[] = {
+ NULL,
+ "SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT",
+ "SSH_DISCONNECT_PROTOCOL_ERROR",
+ "SSH_DISCONNECT_KEY_EXCHANGE_FAILED",
+ "SSH_DISCONNECT_HOST_AUTHENTICATION_FAILED",
+ "SSH_DISCONNECT_MAC_ERROR",
+ "SSH_DISCONNECT_COMPRESSION_ERROR",
+ "SSH_DISCONNECT_SERVICE_NOT_AVAILABLE",
+ "SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED",
+ "SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE",
+ "SSH_DISCONNECT_CONNECTION_LOST",
+ "SSH_DISCONNECT_BY_APPLICATION",
+ "SSH_DISCONNECT_TOO_MANY_CONNECTIONS",
+ "SSH_DISCONNECT_AUTH_CANCELLED_BY_USER",
+ "SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE",
+ "SSH_DISCONNECT_ILLEGAL_USER_NAME",
+};
#define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED 1 /* 0x1 */
#define SSH2_OPEN_CONNECT_FAILED 2 /* 0x2 */
goto next_packet;
}
+ if (pktin.type == SSH1_MSG_DISCONNECT) {
+ /* log reason code in disconnect message */
+ char buf[256];
+ int msglen = GET_32BIT(pktin.body);
+ int nowlen;
+ strcpy(buf, "Remote sent disconnect: ");
+ nowlen = strlen(buf);
+ if (msglen > sizeof(buf)-nowlen-1)
+ msglen = sizeof(buf)-nowlen-1;
+ memcpy(buf+nowlen, pktin.body+4, msglen);
+ buf[nowlen+msglen] = '\0';
+ logevent(buf);
+ }
+
crFinish(0);
}
if (pktin.type == SSH2_MSG_IGNORE || pktin.type == SSH2_MSG_DEBUG)
goto next_packet; /* FIXME: print DEBUG message */
+ if (pktin.type == SSH2_MSG_DISCONNECT) {
+ /* log reason code in disconnect message */
+ char buf[256];
+ int reason = GET_32BIT(pktin.data+6);
+ int msglen = GET_32BIT(pktin.data+10);
+ int nowlen;
+ if (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) {
+ sprintf(buf, "Received disconnect message (%s)",
+ ssh2_disconnect_reasons[reason]);
+ } else {
+ sprintf(buf, "Received disconnect message (unknown type %d)", reason);
+ }
+ logevent(buf);
+ strcpy(buf, "Disconnection message text: ");
+ nowlen = strlen(buf);
+ if (msglen > sizeof(buf)-nowlen-1)
+ msglen = sizeof(buf)-nowlen-1;
+ memcpy(buf+nowlen, pktin.data+14, msglen);
+ buf[nowlen+msglen] = '\0';
+ logevent(buf);
+ }
+
crFinish(0);
}
}
static char *ssh2_mpint_fmt(Bignum b, int *len) {
unsigned char *p;
- int i, n = (ssh1_bignum_bitcount(b)+7)/8;
+ int i, n = (bignum_bitcount(b)+7)/8;
p = smalloc(n + 1);
if (!p)
fatalbox("out of memory");
char *imp; /* pointer to implementation part */
imp = vstring;
imp += strcspn(imp, "-");
+ if (*imp) imp++;
imp += strcspn(imp, "-");
+ if (*imp) imp++;
ssh_remote_bugs = 0;
}
static int do_ssh_init(unsigned char c) {
- static char *vsp;
+ static char vslen;
static char version[10];
- static char vstring[80];
- static char vlog[sizeof(vstring)+20];
+ static char *vstring;
+ static int vstrsize;
+ static char *vlog;
static int i;
crBegin;
crReturn(1); /* get another character */
}
+ vstring = smalloc(16);
+ vstrsize = 16;
strcpy(vstring, "SSH-");
- vsp = vstring+4;
+ vslen = 4;
i = 0;
while (1) {
crReturn(1); /* get another char */
- if (vsp < vstring+sizeof(vstring)-1)
- *vsp++ = c;
+ if (vslen >= vstrsize-1) {
+ vstrsize += 16;
+ vstring = srealloc(vstring, vstrsize);
+ }
+ vstring[vslen++] = c;
if (i >= 0) {
if (c == '-') {
version[i] = '\0';
ssh_agentfwd_enabled = FALSE;
rdpkt2_state.incoming_sequence = 0;
- *vsp = 0;
+ vstring[vslen] = 0;
+ vlog = smalloc(20 + vslen);
sprintf(vlog, "Server version: %s", vstring);
ssh_detect_bugs(vstring);
vlog[strcspn(vlog, "\r\n")] = '\0';
logevent(vlog);
+ sfree(vlog);
/*
* Server version "1.99" means we can choose whether we use v1
/*
* This is a v2 server. Begin v2 protocol.
*/
- char verstring[80];
+ char verstring[80], vlog[100];
sprintf(verstring, "SSH-2.0-%s", sshver);
SHA_Init(&exhashbase);
/*
*/
sha_string(&exhashbase, verstring, strlen(verstring));
sha_string(&exhashbase, vstring, strcspn(vstring, "\r\n"));
- sprintf(vstring, "%s\n", verstring);
sprintf(vlog, "We claim version: %s", verstring);
logevent(vlog);
+ strcat(verstring, "\n");
logevent("Using SSH protocol version 2");
- sk_write(s, vstring, strlen(vstring));
+ sk_write(s, verstring, strlen(verstring));
ssh_protocol = ssh2_protocol;
ssh_version = 2;
s_rdpkt = ssh2_rdpkt;
/*
* This is a v1 server. Begin v1 protocol.
*/
- sprintf(vstring, "SSH-%s-%s\n",
+ char verstring[80], vlog[100];
+ sprintf(verstring, "SSH-%s-%s",
(ssh_versioncmp(version, "1.5") <= 0 ? version : "1.5"),
sshver);
- sprintf(vlog, "We claim version: %s", vstring);
- vlog[strcspn(vlog, "\r\n")] = '\0';
+ sprintf(vlog, "We claim version: %s", verstring);
logevent(vlog);
+ strcat(verstring, "\n");
logevent("Using SSH protocol version 1");
- sk_write(s, vstring, strlen(vstring));
+ sk_write(s, verstring, strlen(verstring));
ssh_protocol = ssh1_protocol;
ssh_version = 1;
s_rdpkt = ssh1_rdpkt;
}
ssh_state = SSH_STATE_BEFORE_SIZE;
+ sfree(vstring);
+
crFinish(0);
}
if ((supported_ciphers_mask & (1 << cipher_type)) == 0) {
c_write_str("Selected cipher not supported, falling back to 3DES\r\n");
cipher_type = SSH_CIPHER_3DES;
+ if ((supported_ciphers_mask & (1 << cipher_type)) == 0) {
+ bombout(("Server violates SSH 1 protocol by "
+ "not supporting 3DES encryption"));
+ crReturn(0);
+ }
}
switch (cipher_type) {
case SSH_CIPHER_3DES: logevent("Using 3DES encryption"); break;
PUT_32BIT(agentreq, len);
q = agentreq + 4;
*q++ = SSH1_AGENTC_RSA_CHALLENGE;
- PUT_32BIT(q, ssh1_bignum_bitcount(key.modulus));
+ PUT_32BIT(q, bignum_bitcount(key.modulus));
q += 4;
q += ssh1_write_bignum(q, key.exponent);
q += ssh1_write_bignum(q, key.modulus);
if (c) {
int closetype;
closetype = (pktin.type == SSH1_MSG_CHANNEL_CLOSE ? 1 : 2);
- send_packet(pktin.type, PKT_INT, c->remoteid, PKT_END);
+ if (!(c->closes & closetype))
+ send_packet(pktin.type, PKT_INT, c->remoteid, PKT_END);
if ((c->closes == 0) && (c->type == CHAN_X11)) {
logevent("X11 connection closed");
assert(c->u.x11.s != NULL);
if (pktin.type != SSH2_MSG_USERAUTH_FAILURE) {
bombout(("Strange packet received during authentication: type %d",
pktin.type));
+ crReturnV;
}
gotit = FALSE;