From 00db133f300dd6aa08111d2b42c749a940ecede9 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 14 Dec 2001 14:57:50 +0000 Subject: [PATCH] Retired the #ifdef DUMP_PACKETS stuff in ssh.c because I'm utterly sick of recompiling to enable packet dumps. SSH packet dumping is now provided as a logging option, and dumps to putty.log like all the other logging options. While I'm at it I cleaned up the format so that packet types are translated into strings for easy browsing. POSSIBLE SIDE EFFECT: in the course of this work I had to re-enable the SSH1 packet length checks which it turns out hadn't actually been active for some time, so it's possible things might break as a result. If need be I can always disable those checks for the 0.52 release and think about it more carefully later. git-svn-id: svn://svn.tartarus.org/sgt/putty@1493 cda61777-01e9-0310-a592-d414129be87e --- Makefile | 7 ++- doc/config.but | 10 +++- logging.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ plink.c | 38 +++++++++++++ psftp.c | 38 +++++++++++++ putty.h | 10 +++- scp.c | 38 +++++++++++++ ssh.c | 176 +++++++++++++++++++++++++++++++++++++++++--------------- terminal.c | 139 -------------------------------------------- windlg.c | 25 +++++--- window.c | 10 ++-- 11 files changed, 465 insertions(+), 203 deletions(-) create mode 100644 logging.c diff --git a/Makefile b/Makefile index ea73ed47..38a3c61f 100644 --- a/Makefile +++ b/Makefile @@ -88,7 +88,7 @@ RES=res ##-- objects putty puttytel GOBJS1 = window.$(OBJ) windlg.$(OBJ) winctrls.$(OBJ) terminal.$(OBJ) -GOBJS2 = sizetip.$(OBJ) wcwidth.$(OBJ) unicode.$(OBJ) +GOBJS2 = sizetip.$(OBJ) wcwidth.$(OBJ) unicode.$(OBJ) logging.$(OBJ) ##-- objects putty puttytel plink LOBJS1 = telnet.$(OBJ) raw.$(OBJ) rlogin.$(OBJ) ldisc.$(OBJ) winnet.$(OBJ) ##-- objects putty plink @@ -96,13 +96,13 @@ POBJS = be_all.$(OBJ) ##-- objects puttytel TOBJS = be_nossh.$(OBJ) ##-- objects plink -PLOBJS = plink.$(OBJ) +PLOBJS = plink.$(OBJ) logging.$(OBJ) ##-- objects pscp SOBJS = scp.$(OBJ) winnet.$(OBJ) be_none.$(OBJ) wildcard.$(OBJ) ##-- objects psftp FOBJS = psftp.$(OBJ) winnet.$(OBJ) be_none.$(OBJ) ##-- objects pscp psftp -SFOBJS = sftp.$(OBJ) int64.$(OBJ) +SFOBJS = sftp.$(OBJ) int64.$(OBJ) logging.$(OBJ) ##-- objects putty puttytel pscp psftp plink MOBJS = misc.$(OBJ) version.$(OBJ) winstore.$(OBJ) settings.$(OBJ) MOBJ2 = tree234.$(OBJ) @@ -321,6 +321,7 @@ sshzlib.$(OBJ): sshzlib.c network.h int64.h puttymem.h ssh.h ssl.$(OBJ): ssl.c network.h asnerror.h misc.h cert.h crypto.h ssl.h int64.h puttymem.h telnet.$(OBJ): telnet.c network.h misc.h puttymem.h putty.h terminal.$(OBJ): terminal.c network.h misc.h puttymem.h putty.h tree234.h +logging.$(OBJ): logging.c misc.h puttymem.h putty.h test.$(OBJ): test.c network.h int64.h puttymem.h ssh.h tree234.$(OBJ): tree234.c tree234.h unicode.$(OBJ): unicode.c network.h misc.h puttymem.h putty.h diff --git a/doc/config.but b/doc/config.but index 7e084731..2c14f698 100644 --- a/doc/config.but +++ b/doc/config.but @@ -1,4 +1,4 @@ -\versionid $Id: config.but,v 1.20 2001/12/14 12:48:24 simon Exp $ +\versionid $Id: config.but,v 1.21 2001/12/14 14:57:50 simon Exp $ \C{config} Configuring PuTTY @@ -136,6 +136,14 @@ can record everything that went to the terminal, so that someone else can replay the session later in slow motion and watch to see what went wrong. +\b \q{Log SSH packet data}. In this mode (which is only used by SSH +connections), the SSH message packets sent over the encrypted +connection are written to the log file. You might need this to debug +a network-level problem, or more likely to send to the PuTTY authors +as part of a bug report. \e{BE WARNED} that if you log in using a +password, the password will appear in the log file, so be sure to +edit it out before sending the log file to anyone else! + \S{config-logfilename} \q{Log file name} \cfg{winhelp-topic}{logging.filename} diff --git a/logging.c b/logging.c new file mode 100644 index 00000000..3caa94a4 --- /dev/null +++ b/logging.c @@ -0,0 +1,177 @@ +#include + +#include +#include +#include + +#include +#include + +#include "putty.h" + +/* log session to file stuff ... */ +static FILE *lgfp = NULL; +static char timdatbuf[20]; +static char currlogfilename[FILENAME_MAX]; + +static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm); + +/* + * Log session traffic. + */ +void logtraffic(unsigned char c, int logmode) +{ + if (cfg.logtype > 0) { + if (cfg.logtype == logmode) { + /* deferred open file from pgm start? */ + if (!lgfp) + logfopen(); + if (lgfp) + fputc(c, lgfp); + } + } +} + +/* + * Log an SSH packet. + */ +void log_packet(int direction, int type, char *texttype, void *data, int len) +{ + int i, j, c; + char dumpdata[80], smalldata[5]; + + if (cfg.logtype != LGTYP_PACKETS) + return; + if (!lgfp) + logfopen(); + if (lgfp) { + fprintf(lgfp, "%s packet type %d / 0x%02x (%s)\n", + direction == PKT_INCOMING ? "Incoming" : "Outgoing", + type, type, texttype); + for (i = 0; i < len; i += 16) { + sprintf(dumpdata, " %08x%*s\n", i, 1+3*16+2+16, ""); + for (j = 0; j < 16 && i+j < len; j++) { + int c = ((unsigned char *)data)[i+j]; + sprintf(smalldata, "%02x", c); + dumpdata[10+2+3*j] = smalldata[0]; + dumpdata[10+2+3*j+1] = smalldata[1]; + dumpdata[10+1+3*16+2+j] = (isprint(c) ? c : '.'); + } + strcpy(dumpdata + 10+1+3*16+2+j, "\n"); + fputs(dumpdata, lgfp); + } + } +} + +/* open log file append/overwrite mode */ +void logfopen(void) +{ + char buf[256]; + time_t t; + struct tm tm; + char writemod[4]; + + if (!cfg.logtype) + return; + sprintf(writemod, "wb"); /* default to rewrite */ + + time(&t); + tm = *localtime(&t); + + /* substitute special codes in file name */ + xlatlognam(currlogfilename,cfg.logfilename,cfg.host, &tm); + + lgfp = fopen(currlogfilename, "r"); /* file already present? */ + if (lgfp) { + int i; + fclose(lgfp); + i = askappend(currlogfilename); + if (i == 1) + writemod[0] = 'a'; /* set append mode */ + else if (i == 0) { /* cancelled */ + lgfp = NULL; + cfg.logtype = 0; /* disable logging */ + return; + } + } + + lgfp = fopen(currlogfilename, writemod); + if (lgfp) { /* enter into event log */ + sprintf(buf, "%s session log (%s mode) to file : ", + (writemod[0] == 'a') ? "Appending" : "Writing new", + (cfg.logtype == LGTYP_ASCII ? "ASCII" : + cfg.logtype == LGTYP_DEBUG ? "raw" : "")); + /* Make sure we do not exceed the output buffer size */ + strncat(buf, currlogfilename, 128); + buf[strlen(buf)] = '\0'; + logevent(buf); + + /* --- write header line into log file */ + fputs("=~=~=~=~=~=~=~=~=~=~=~= PuTTY log ", lgfp); + strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm); + fputs(buf, lgfp); + fputs(" =~=~=~=~=~=~=~=~=~=~=~=\r\n", lgfp); + } +} + +void logfclose(void) +{ + if (lgfp) { + fclose(lgfp); + lgfp = NULL; + } +} + +/* + * translate format codes into time/date strings + * and insert them into log file name + * + * "&Y":YYYY "&m":MM "&d":DD "&T":hhmm "&h": "&&":& + */ +static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm) { + char buf[10], *bufp; + int size; + char *ds = d; /* save start pos. */ + int len = FILENAME_MAX-1; + + while (*s) { + /* Let (bufp, len) be the string to append. */ + bufp = buf; /* don't usually override this */ + if (*s == '&') { + char c; + s++; + if (*s) switch (c = *s++, tolower(c)) { + case 'y': + size = strftime(buf, sizeof(buf), "%Y", tm); + break; + case 'm': + size = strftime(buf, sizeof(buf), "%m", tm); + break; + case 'd': + size = strftime(buf, sizeof(buf), "%d", tm); + break; + case 't': + size = strftime(buf, sizeof(buf), "%H%M%S", tm); + break; + case 'h': + bufp = hostname; + size = strlen(bufp); + break; + default: + buf[0] = '&'; + size = 1; + if (c != '&') + buf[size++] = c; + } + } else { + buf[0] = *s++; + size = 1; + } + if (size > len) + size = len; + memcpy(d, bufp, size); + d += size; + len -= size; + } + *d = '\0'; +} diff --git a/plink.c b/plink.c index 7023f9d1..6c211503 100644 --- a/plink.c +++ b/plink.c @@ -163,6 +163,44 @@ void askcipher(char *ciphername, int cs) } /* + * Ask whether to wipe a session log file before writing to it. + * Returns 2 for wipe, 1 for append, 0 for cancel (don't log). + */ +int askappend(char *filename) +{ + HANDLE hin; + DWORD savemode, i; + + static const char msgtemplate[] = + "The session log file \"%.*s\" already exists.\n" + "You can overwrite it with a new session log,\n" + "append your session log to the end of it,\n" + "or disable session logging for this session.\n" + "Enter \"y\" to wipe the file, \"n\" to append to it,\n" + "or just press Return to disable logging.\n" + "Wipe the log file? (y/n, Return cancels logging) "; + + char line[32]; + + fprintf(stderr, msgtemplate, FILENAME_MAX, filename); + fflush(stderr); + + hin = GetStdHandle(STD_INPUT_HANDLE); + GetConsoleMode(hin, &savemode); + SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT | + ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)); + ReadFile(hin, line, sizeof(line) - 1, &i, NULL); + SetConsoleMode(hin, savemode); + + if (line[0] == 'y' || line[0] == 'Y') + return 2; + else if (line[0] == 'n' || line[0] == 'N') + return 1; + else + return 0; +} + +/* * Warn about the obsolescent key file format. */ void old_keyfile_warning(void) diff --git a/psftp.c b/psftp.c index feefbbc0..2923e732 100644 --- a/psftp.c +++ b/psftp.c @@ -1456,6 +1456,44 @@ void askcipher(char *ciphername, int cs) } /* + * Ask whether to wipe a session log file before writing to it. + * Returns 2 for wipe, 1 for append, 0 for cancel (don't log). + */ +int askappend(char *filename) +{ + HANDLE hin; + DWORD savemode, i; + + static const char msgtemplate[] = + "The session log file \"%.*s\" already exists.\n" + "You can overwrite it with a new session log,\n" + "append your session log to the end of it,\n" + "or disable session logging for this session.\n" + "Enter \"y\" to wipe the file, \"n\" to append to it,\n" + "or just press Return to disable logging.\n" + "Wipe the log file? (y/n, Return cancels logging) "; + + char line[32]; + + fprintf(stderr, msgtemplate, FILENAME_MAX, filename); + fflush(stderr); + + hin = GetStdHandle(STD_INPUT_HANDLE); + GetConsoleMode(hin, &savemode); + SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT | + ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)); + ReadFile(hin, line, sizeof(line) - 1, &i, NULL); + SetConsoleMode(hin, savemode); + + if (line[0] == 'y' || line[0] == 'Y') + return 2; + else if (line[0] == 'n' || line[0] == 'N') + return 1; + else + return 0; +} + +/* * Warn about the obsolescent key file format. */ void old_keyfile_warning(void) diff --git a/putty.h b/putty.h index 4302b849..27a6564e 100644 --- a/putty.h +++ b/putty.h @@ -130,7 +130,8 @@ GLOBAL unsigned char unitab_ctrl[256]; #define LGXF_ASK -1 /* existing logfile ask */ #define LGTYP_NONE 0 /* logmode: no logging */ #define LGTYP_ASCII 1 /* logmode: pure ascii */ -#define LGTYP_DEBUG 2 /* logmode: all chars of taffic */ +#define LGTYP_DEBUG 2 /* logmode: all chars of traffic */ +#define LGTYP_PACKETS 3 /* logmode: SSH data packets */ GLOBAL char *logfile; /* @@ -486,6 +487,13 @@ void logfclose(void); void term_copyall(void); /* + * Exports from logging.c. + */ +void logtraffic(unsigned char c, int logmode); +enum { PKT_INCOMING, PKT_OUTGOING }; +void log_packet(int direction, int type, char *texttype, void *data, int len); + +/* * Exports from raw.c. */ diff --git a/scp.c b/scp.c index c40d7cce..45930c0e 100644 --- a/scp.c +++ b/scp.c @@ -227,6 +227,44 @@ void askcipher(char *ciphername, int cs) } /* + * Ask whether to wipe a session log file before writing to it. + * Returns 2 for wipe, 1 for append, 0 for cancel (don't log). + */ +int askappend(char *filename) +{ + HANDLE hin; + DWORD savemode, i; + + static const char msgtemplate[] = + "The session log file \"%.*s\" already exists.\n" + "You can overwrite it with a new session log,\n" + "append your session log to the end of it,\n" + "or disable session logging for this session.\n" + "Enter \"y\" to wipe the file, \"n\" to append to it,\n" + "or just press Return to disable logging.\n" + "Wipe the log file? (y/n, Return cancels logging) "; + + char line[32]; + + fprintf(stderr, msgtemplate, FILENAME_MAX, filename); + fflush(stderr); + + hin = GetStdHandle(STD_INPUT_HANDLE); + GetConsoleMode(hin, &savemode); + SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT | + ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)); + ReadFile(hin, line, sizeof(line) - 1, &i, NULL); + SetConsoleMode(hin, savemode); + + if (line[0] == 'y' || line[0] == 'Y') + return 2; + else if (line[0] == 'n' || line[0] == 'N') + return 1; + else + return 0; +} + +/* * Warn about the obsolescent key file format. */ void old_keyfile_warning(void) 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; diff --git a/terminal.c b/terminal.c index 77bb3905..2962b0a0 100644 --- a/terminal.c +++ b/terminal.c @@ -206,10 +206,6 @@ static void erase_lots(int, int, int); static void swap_screen(int); static void update_sbar(void); static void deselect(void); -/* log session to file stuff ... */ -static FILE *lgfp = NULL; -static void logtraffic(unsigned char c, int logmode); -static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm); /* * Resize a line to make it `cols' columns wide. @@ -3630,138 +3626,3 @@ int from_backend(int is_stderr, char *data, int len) */ return 0; } - -/* - * Log session traffic. - */ -void logtraffic(unsigned char c, int logmode) -{ - if (cfg.logtype > 0) { - if (cfg.logtype == logmode) { - /* deferred open file from pgm start? */ - if (!lgfp) - logfopen(); - if (lgfp) - fputc(c, lgfp); - } - } -} - -void settimstr(char *ta, int no_sec); -char *subslfcode(char *dest, char *src, char *dstrt); -char *stpncpy(char *dst, const char *src, size_t maxlen); -char timdatbuf[20]; -char currlogfilename[FILENAME_MAX]; - -/* open log file append/overwrite mode */ -void logfopen(void) -{ - char buf[256]; - time_t t; - struct tm tm; - char writemod[4]; - - if (!cfg.logtype) - return; - sprintf(writemod, "wb"); /* default to rewrite */ - - time(&t); - tm = *localtime(&t); - - /* substitute special codes in file name */ - xlatlognam(currlogfilename,cfg.logfilename,cfg.host, &tm); - - lgfp = fopen(currlogfilename, "r"); /* file already present? */ - if (lgfp) { - int i; - fclose(lgfp); - i = askappend(currlogfilename); - if (i == 1) - writemod[0] = 'a'; /* set append mode */ - else if (i == 0) { /* cancelled */ - lgfp = NULL; - cfg.logtype = 0; /* disable logging */ - return; - } - } - - lgfp = fopen(currlogfilename, writemod); - if (lgfp) { /* enter into event log */ - sprintf(buf, "%s session log (%s mode) to file : ", - (writemod[0] == 'a') ? "Appending" : "Writing new", - (cfg.logtype == LGTYP_ASCII ? "ASCII" : - cfg.logtype == LGTYP_DEBUG ? "raw" : "")); - /* Make sure we do not exceed the output buffer size */ - strncat(buf, currlogfilename, 128); - buf[strlen(buf)] = '\0'; - logevent(buf); - - /* --- write header line into log file */ - fputs("=~=~=~=~=~=~=~=~=~=~=~= PuTTY log ", lgfp); - strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm); - fputs(buf, lgfp); - fputs(" =~=~=~=~=~=~=~=~=~=~=~=\r\n", lgfp); - } -} - -void logfclose(void) -{ - if (lgfp) { - fclose(lgfp); - lgfp = NULL; - } -} - -/* - * translate format codes into time/date strings - * and insert them into log file name - * - * "&Y":YYYY "&m":MM "&d":DD "&T":hhmm "&h": "&&":& - */ -static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm) { - char buf[10], *bufp; - int size; - char *ds = d; /* save start pos. */ - int len = FILENAME_MAX-1; - - while (*s) { - /* Let (bufp, len) be the string to append. */ - bufp = buf; /* don't usually override this */ - if (*s == '&') { - char c; - s++; - if (*s) switch (c = *s++, tolower(c)) { - case 'y': - size = strftime(buf, sizeof(buf), "%Y", tm); - break; - case 'm': - size = strftime(buf, sizeof(buf), "%m", tm); - break; - case 'd': - size = strftime(buf, sizeof(buf), "%d", tm); - break; - case 't': - size = strftime(buf, sizeof(buf), "%H%M%S", tm); - break; - case 'h': - bufp = hostname; - size = strlen(bufp); - break; - default: - buf[0] = '&'; - size = 1; - if (c != '&') - buf[size++] = c; - } - } else { - buf[0] = *s++; - size = 1; - } - if (size > len) - size = len; - memcpy(d, bufp, size); - d += size; - len -= size; - } - *d = '\0'; -} diff --git a/windlg.c b/windlg.c index 9da02256..c3f13b75 100644 --- a/windlg.c +++ b/windlg.c @@ -257,6 +257,7 @@ enum { IDCX_ABOUT = IDC_LSTATOFF, IDC_LSTATASCII, IDC_LSTATRAW, + IDC_LSTATPACKET, IDC_LGFSTATIC, IDC_LGFEDIT, IDC_LGFBUTTON, @@ -621,6 +622,7 @@ char *help_context_cmd(int id) case IDC_LSTATOFF: case IDC_LSTATASCII: case IDC_LSTATRAW: + case IDC_LSTATPACKET: return "JI(`',`logging.main')"; case IDC_LGFSTATIC: case IDC_LGFEDIT: @@ -1032,9 +1034,11 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess) SetDlgItemText(hwnd, IDC_RLLUSEREDIT, cfg.localusername); SetDlgItemText(hwnd, IDC_LOGEDIT, cfg.username); SetDlgItemText(hwnd, IDC_LGFEDIT, cfg.logfilename); - CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATRAW, - cfg.logtype == 0 ? IDC_LSTATOFF : - cfg.logtype == 1 ? IDC_LSTATASCII : IDC_LSTATRAW); + CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATPACKET, + cfg.logtype == LGTYP_NONE ? IDC_LSTATOFF : + cfg.logtype == LGTYP_ASCII ? IDC_LSTATASCII : + cfg.logtype == LGTYP_DEBUG ? IDC_LSTATRAW : + IDC_LSTATPACKET); CheckRadioButton(hwnd, IDC_LSTATXOVR, IDC_LSTATXASK, cfg.logxfovr == LGXF_OVR ? IDC_LSTATXOVR : cfg.logxfovr == LGXF_ASK ? IDC_LSTATXASK : @@ -1254,7 +1258,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel) } if (panel == loggingpanelstart) { - /* The Logging panel. Accelerators used: [acgo] tplfwe */ + /* The Logging panel. Accelerators used: [acgo] tplsfwe */ struct ctlpos cp; ctlposinit(&cp, hwnd, 80, 3, 13); bartitle(&cp, "Options controlling session logging", @@ -1264,7 +1268,9 @@ static void create_controls(HWND hwnd, int dlgtype, int panel) "Session logging:", IDC_LSTATSTATIC, "Logging &turned off completely", IDC_LSTATOFF, "Log &printable output only", IDC_LSTATASCII, - "&Log all session output", IDC_LSTATRAW, NULL); + "&Log all session output", IDC_LSTATRAW, + "Log &SSH packet data", IDC_LSTATPACKET, + NULL); editbutton(&cp, "Log &file name:", IDC_LGFSTATIC, IDC_LGFEDIT, "Bro&wse...", IDC_LGFBUTTON); @@ -2608,14 +2614,17 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg, case IDC_LSTATOFF: case IDC_LSTATASCII: case IDC_LSTATRAW: + case IDC_LSTATPACKET: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DOUBLECLICKED) { if (IsDlgButtonChecked(hwnd, IDC_LSTATOFF)) - cfg.logtype = 0; + cfg.logtype = LGTYP_NONE; if (IsDlgButtonChecked(hwnd, IDC_LSTATASCII)) - cfg.logtype = 1; + cfg.logtype = LGTYP_ASCII; if (IsDlgButtonChecked(hwnd, IDC_LSTATRAW)) - cfg.logtype = 2; + cfg.logtype = LGTYP_DEBUG; + if (IsDlgButtonChecked(hwnd, IDC_LSTATPACKET)) + cfg.logtype = LGTYP_PACKETS; } break; case IDC_LSTATXASK: diff --git a/window.c b/window.c index 52af23e2..54665c97 100644 --- a/window.c +++ b/window.c @@ -633,15 +633,15 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) set_input_locale(GetKeyboardLayout(0)); /* - * Finally show the window! + * Open the initial log file if there is one. */ - ShowWindow(hwnd, show); - SetForegroundWindow(hwnd); + logfopen(); /* - * Open the initial log file if there is one. + * Finally show the window! */ - logfopen(); + ShowWindow(hwnd, show); + SetForegroundWindow(hwnd); /* * Set the palette up. -- 2.11.0