X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/blobdiff_plain/1044621582968fd2dbf5d797b79524f22cfa747f..a8cc197c711b4381e8050e0ecfc3458873f24468:/ssh.c?ds=sidebyside diff --git a/ssh.c b/ssh.c index 627a16f1..08ff8d97 100644 --- a/ssh.c +++ b/ssh.c @@ -118,6 +118,29 @@ #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 */ @@ -510,6 +533,20 @@ next_packet: 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); } @@ -649,6 +686,28 @@ next_packet: 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); } @@ -928,7 +987,7 @@ static void ssh2_pkt_addstring(char *data) { } 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"); @@ -1128,7 +1187,9 @@ static void ssh_detect_bugs(char *vstring) { char *imp; /* pointer to implementation part */ imp = vstring; imp += strcspn(imp, "-"); + if (*imp) imp++; imp += strcspn(imp, "-"); + if (*imp) imp++; ssh_remote_bugs = 0; @@ -1156,10 +1217,11 @@ static void ssh_detect_bugs(char *vstring) { } 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; @@ -1179,13 +1241,18 @@ static int do_ssh_init(unsigned char c) { 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'; @@ -1200,11 +1267,13 @@ static int do_ssh_init(unsigned char c) { 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 @@ -1214,7 +1283,7 @@ static int do_ssh_init(unsigned char c) { /* * 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); /* @@ -1222,11 +1291,11 @@ static int do_ssh_init(unsigned char c) { */ 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; @@ -1234,20 +1303,23 @@ static int do_ssh_init(unsigned char c) { /* * 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); } @@ -1497,6 +1569,11 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) 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; @@ -1676,7 +1753,7 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) 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); @@ -2234,7 +2311,8 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) { 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); @@ -3003,6 +3081,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) if (pktin.type != SSH2_MSG_USERAUTH_FAILURE) { bombout(("Strange packet received during authentication: type %d", pktin.type)); + crReturnV; } gotit = FALSE;