X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/babac7bd70fda1ec0c9810c8f4ccf08cfa1e31fb..00db133f300dd6aa08111d2b42c749a940ecede9:/ssh.c diff --git a/ssh.c b/ssh.c index 9f27e3a9..bc7f5bf6 100644 --- a/ssh.c +++ b/ssh.c @@ -15,9 +15,6 @@ #define TRUE 1 #endif -/* uncomment this for packet level debugging */ -/* #define DUMP_PACKETS */ - #define logevent(s) { logevent(s); \ if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) \ { fprintf(stderr, "%s\n", s); fflush(stderr); } } @@ -112,6 +109,17 @@ #define SSH2_MSG_CHANNEL_SUCCESS 99 /* 0x63 */ #define SSH2_MSG_CHANNEL_FAILURE 100 /* 0x64 */ +/* + * Packet type contexts, so that ssh2_pkt_type can correctly decode + * the ambiguous type numbers back into the correct type strings. + */ +#define SSH2_PKTCTX_DHGROUP1 0x0001 +#define SSH2_PKTCTX_DHGEX 0x0002 +#define SSH2_PKTCTX_PUBLICKEY 0x0010 +#define SSH2_PKTCTX_PASSWORD 0x0020 +#define SSH2_PKTCTX_KBDINTER 0x0040 +#define SSH2_PKTCTX_AUTH_MASK 0x00F0 + #define SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1 /* 0x1 */ #define SSH2_DISCONNECT_PROTOCOL_ERROR 2 /* 0x2 */ #define SSH2_DISCONNECT_KEY_EXCHANGE_FAILED 3 /* 0x3 */ @@ -161,6 +169,97 @@ static const char *const ssh2_disconnect_reasons[] = { #define BUG_SSH2_HMAC 2 #define BUG_NEEDS_SSH1_PLAIN_PASSWORD 4 +static int ssh_pkt_ctx = 0; + +#define translate(x) if (type == x) return #x +#define translatec(x,ctx) if (type == x && (ssh_pkt_ctx & ctx)) return #x +char *ssh1_pkt_type(int type) +{ + translate(SSH1_MSG_DISCONNECT); + translate(SSH1_SMSG_PUBLIC_KEY); + translate(SSH1_CMSG_SESSION_KEY); + translate(SSH1_CMSG_USER); + translate(SSH1_CMSG_AUTH_RSA); + translate(SSH1_SMSG_AUTH_RSA_CHALLENGE); + translate(SSH1_CMSG_AUTH_RSA_RESPONSE); + translate(SSH1_CMSG_AUTH_PASSWORD); + translate(SSH1_CMSG_REQUEST_PTY); + translate(SSH1_CMSG_WINDOW_SIZE); + translate(SSH1_CMSG_EXEC_SHELL); + translate(SSH1_CMSG_EXEC_CMD); + translate(SSH1_SMSG_SUCCESS); + translate(SSH1_SMSG_FAILURE); + translate(SSH1_CMSG_STDIN_DATA); + translate(SSH1_SMSG_STDOUT_DATA); + translate(SSH1_SMSG_STDERR_DATA); + translate(SSH1_CMSG_EOF); + translate(SSH1_SMSG_EXIT_STATUS); + translate(SSH1_MSG_CHANNEL_OPEN_CONFIRMATION); + translate(SSH1_MSG_CHANNEL_OPEN_FAILURE); + translate(SSH1_MSG_CHANNEL_DATA); + translate(SSH1_MSG_CHANNEL_CLOSE); + translate(SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION); + translate(SSH1_SMSG_X11_OPEN); + translate(SSH1_CMSG_PORT_FORWARD_REQUEST); + translate(SSH1_MSG_PORT_OPEN); + translate(SSH1_CMSG_AGENT_REQUEST_FORWARDING); + translate(SSH1_SMSG_AGENT_OPEN); + translate(SSH1_MSG_IGNORE); + translate(SSH1_CMSG_EXIT_CONFIRMATION); + translate(SSH1_CMSG_X11_REQUEST_FORWARDING); + translate(SSH1_CMSG_AUTH_RHOSTS_RSA); + translate(SSH1_MSG_DEBUG); + translate(SSH1_CMSG_REQUEST_COMPRESSION); + translate(SSH1_CMSG_AUTH_TIS); + translate(SSH1_SMSG_AUTH_TIS_CHALLENGE); + translate(SSH1_CMSG_AUTH_TIS_RESPONSE); + translate(SSH1_CMSG_AUTH_CCARD); + translate(SSH1_SMSG_AUTH_CCARD_CHALLENGE); + translate(SSH1_CMSG_AUTH_CCARD_RESPONSE); + return "unknown"; +} +char *ssh2_pkt_type(int type) +{ + translate(SSH2_MSG_DISCONNECT); + translate(SSH2_MSG_IGNORE); + translate(SSH2_MSG_UNIMPLEMENTED); + translate(SSH2_MSG_DEBUG); + translate(SSH2_MSG_SERVICE_REQUEST); + translate(SSH2_MSG_SERVICE_ACCEPT); + translate(SSH2_MSG_KEXINIT); + translate(SSH2_MSG_NEWKEYS); + translatec(SSH2_MSG_KEXDH_INIT, SSH2_PKTCTX_DHGROUP1); + translatec(SSH2_MSG_KEXDH_REPLY, SSH2_PKTCTX_DHGROUP1); + translatec(SSH2_MSG_KEX_DH_GEX_REQUEST, SSH2_PKTCTX_DHGEX); + translatec(SSH2_MSG_KEX_DH_GEX_GROUP, SSH2_PKTCTX_DHGEX); + translatec(SSH2_MSG_KEX_DH_GEX_INIT, SSH2_PKTCTX_DHGEX); + translatec(SSH2_MSG_KEX_DH_GEX_REPLY, SSH2_PKTCTX_DHGEX); + translate(SSH2_MSG_USERAUTH_REQUEST); + translate(SSH2_MSG_USERAUTH_FAILURE); + translate(SSH2_MSG_USERAUTH_SUCCESS); + translate(SSH2_MSG_USERAUTH_BANNER); + translatec(SSH2_MSG_USERAUTH_PK_OK, SSH2_PKTCTX_PUBLICKEY); + translatec(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, SSH2_PKTCTX_PASSWORD); + translatec(SSH2_MSG_USERAUTH_INFO_REQUEST, SSH2_PKTCTX_KBDINTER); + translatec(SSH2_MSG_USERAUTH_INFO_RESPONSE, SSH2_PKTCTX_KBDINTER); + translate(SSH2_MSG_GLOBAL_REQUEST); + translate(SSH2_MSG_REQUEST_SUCCESS); + translate(SSH2_MSG_REQUEST_FAILURE); + translate(SSH2_MSG_CHANNEL_OPEN); + translate(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); + translate(SSH2_MSG_CHANNEL_OPEN_FAILURE); + translate(SSH2_MSG_CHANNEL_WINDOW_ADJUST); + translate(SSH2_MSG_CHANNEL_DATA); + translate(SSH2_MSG_CHANNEL_EXTENDED_DATA); + translate(SSH2_MSG_CHANNEL_EOF); + translate(SSH2_MSG_CHANNEL_CLOSE); + translate(SSH2_MSG_CHANNEL_REQUEST); + translate(SSH2_MSG_CHANNEL_SUCCESS); + translate(SSH2_MSG_CHANNEL_FAILURE); + return "unknown"; +} +#undef translate +#undef translatec #define GET_32BIT(cp) \ (((unsigned long)(unsigned char)(cp)[0] << 24) | \ @@ -626,10 +725,6 @@ static int ssh1_rdpkt(unsigned char **data, int *datalen) if (cipher) cipher->decrypt(pktin.data, st->biglen); -#ifdef DUMP_PACKETS - debug(("Got packet len=%d pad=%d\n", st->len, st->pad)); - dmemdump(pktin.data, st->biglen); -#endif st->realcrc = crc32(pktin.data, st->biglen - 4); st->gotcrc = GET_32BIT(pktin.data + st->biglen - 4); @@ -643,10 +738,6 @@ static int ssh1_rdpkt(unsigned char **data, int *datalen) if (ssh1_compressing) { unsigned char *decompblk; int decomplen; -#ifdef DUMP_PACKETS - debug(("Packet payload pre-decompression:\n")); - dmemdump(pktin.body - 1, pktin.length + 1); -#endif zlib_decompress_block(pktin.body - 1, pktin.length + 1, &decompblk, &decomplen); @@ -661,12 +752,13 @@ static int ssh1_rdpkt(unsigned char **data, int *datalen) memcpy(pktin.body - 1, decompblk, decomplen); sfree(decompblk); pktin.length = decomplen - 1; -#ifdef DUMP_PACKETS - debug(("Packet payload post-decompression:\n")); - dmemdump(pktin.body - 1, pktin.length + 1); -#endif } + pktin.type = pktin.body[-1]; + + log_packet(PKT_INCOMING, pktin.type, ssh1_pkt_type(pktin.type), + pktin.body, pktin.length); + if (pktin.type == SSH1_SMSG_STDOUT_DATA || pktin.type == SSH1_SMSG_STDERR_DATA || pktin.type == SSH1_MSG_DEBUG || @@ -679,8 +771,6 @@ static int ssh1_rdpkt(unsigned char **data, int *datalen) } } - pktin.type = pktin.body[-1]; - if (pktin.type == SSH1_MSG_DEBUG) { /* log debug message */ char buf[80]; @@ -807,11 +897,6 @@ static int ssh2_rdpkt(unsigned char **data, int *datalen) sccipher->decrypt(pktin.data + st->cipherblk, st->packetlen - st->cipherblk); -#ifdef DUMP_PACKETS - debug(("Got packet len=%d pad=%d\n", st->len, st->pad)); - dmemdump(pktin.data, st->packetlen); -#endif - /* * Check the MAC. */ @@ -844,11 +929,6 @@ static int ssh2_rdpkt(unsigned char **data, int *datalen) } pktin.length = 5 + newlen; memcpy(pktin.data + 5, newpayload, newlen); -#ifdef DUMP_PACKETS - debug(("Post-decompression payload:\n")); - dmemdump(pktin.data + 5, newlen); -#endif - sfree(newpayload); } } @@ -856,6 +936,9 @@ static int ssh2_rdpkt(unsigned char **data, int *datalen) pktin.savedpos = 6; pktin.type = pktin.data[5]; + log_packet(PKT_INCOMING, pktin.type, ssh2_pkt_type(pktin.type), + pktin.data+6, pktin.length-6); + if (pktin.type == SSH2_MSG_IGNORE || pktin.type == SSH2_MSG_DEBUG) goto next_packet; /* FIXME: print DEBUG message */ @@ -930,13 +1013,12 @@ static int s_wrpkt_prepare(void) pktout.body[-1] = pktout.type; + log_packet(PKT_OUTGOING, pktout.type, ssh1_pkt_type(pktout.type), + pktout.body, pktout.length); + if (ssh1_compressing) { unsigned char *compblk; int complen; -#ifdef DUMP_PACKETS - debug(("Packet payload pre-compression:\n")); - dmemdump(pktout.body - 1, pktout.length + 1); -#endif zlib_compress_block(pktout.body - 1, pktout.length + 1, &compblk, &complen); ssh1_pktout_size(complen - 1); @@ -954,10 +1036,6 @@ static int s_wrpkt_prepare(void) PUT_32BIT(pktout.data + biglen, crc); PUT_32BIT(pktout.data, len); -#ifdef DUMP_PACKETS - debug(("Sending packet len=%d\n", biglen + 4)); - dmemdump(pktout.data, biglen + 4); -#endif if (cipher) cipher->encrypt(pktout.data + 4, biglen); @@ -1221,18 +1299,15 @@ static int ssh2_pkt_construct(void) int cipherblk, maclen, padding, i; static unsigned long outgoing_sequence = 0; + log_packet(PKT_OUTGOING, pktout.data[5], ssh2_pkt_type(pktout.data[5]), + pktout.data + 6, pktout.length - 6); + /* * Compress packet payload. */ { unsigned char *newpayload; int newlen; -#ifdef DUMP_PACKETS - if (cscomp && cscomp != &ssh_comp_none) { - debug(("Pre-compression payload:\n")); - dmemdump(pktout.data + 5, pktout.length - 5); - } -#endif if (cscomp && cscomp->compress(pktout.data + 5, pktout.length - 5, &newpayload, &newlen)) { pktout.length = 5; @@ -1261,11 +1336,6 @@ static int ssh2_pkt_construct(void) outgoing_sequence); outgoing_sequence++; /* whether or not we MACed */ -#ifdef DUMP_PACKETS - debug(("Sending packet len=%d\n", pktout.length + padding)); - dmemdump(pktout.data, pktout.length + padding); -#endif - if (cscipher) cscipher->encrypt(pktout.data, pktout.length + padding); @@ -3435,6 +3505,7 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt) */ if (kex == &ssh_diffiehellman_gex) { logevent("Doing Diffie-Hellman group exchange"); + ssh_pkt_ctx |= SSH2_PKTCTX_DHGEX; /* * Work out how big a DH group we will need to allow that * much data. @@ -3455,6 +3526,7 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt) kex_init_value = SSH2_MSG_KEX_DH_GEX_INIT; kex_reply_value = SSH2_MSG_KEX_DH_GEX_REPLY; } else { + ssh_pkt_ctx |= SSH2_PKTCTX_DHGROUP1; dh_setup_group1(); kex_init_value = SSH2_MSG_KEXDH_INIT; kex_reply_value = SSH2_MSG_KEXDH_REPLY; @@ -3798,6 +3870,8 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) * just in case it succeeds, and (b) so that we know what * authentication methods we can usefully try next. */ + ssh_pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK; + ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST); ssh2_pkt_addstring(username); ssh2_pkt_addstring("ssh-connection"); /* service requested */ @@ -3919,6 +3993,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) } method = 0; + ssh_pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK; if (!method && can_pubkey && agent_exists() && !tried_agent) { /* @@ -3930,6 +4005,8 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) static int authed = FALSE; void *r; + ssh_pkt_ctx |= SSH2_PKTCTX_PUBLICKEY; + tried_agent = TRUE; logevent("Pageant is running. Requesting keys."); @@ -4066,6 +4143,8 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) tried_pubkey_config = TRUE; + ssh_pkt_ctx |= SSH2_PKTCTX_PUBLICKEY; + /* * Try the public key supplied in the configuration. * @@ -4118,6 +4197,8 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) type = AUTH_TYPE_KEYBOARD_INTERACTIVE; tried_keyb_inter = TRUE; + ssh_pkt_ctx |= SSH2_PKTCTX_KBDINTER; + ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST); ssh2_pkt_addstring(username); ssh2_pkt_addstring("ssh-connection"); /* service requested */ @@ -4143,6 +4224,8 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) type = AUTH_TYPE_KEYBOARD_INTERACTIVE; tried_keyb_inter = TRUE; + ssh_pkt_ctx |= SSH2_PKTCTX_KBDINTER; + /* We've got packet with that "interactive" info dump banners, and set its prompt as ours */ { @@ -4169,6 +4252,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) if (!method && can_passwd) { method = AUTH_PASSWORD; + ssh_pkt_ctx |= SSH2_PKTCTX_PASSWORD; sprintf(pwprompt, "%.90s@%.90s's password: ", username, savedhost); need_pw = TRUE;