1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

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.

[originally from svn r1493]
This commit is contained in:
Simon Tatham 2001-12-14 14:57:50 +00:00
parent 789bb1e727
commit 3ed0d44f16
11 changed files with 465 additions and 203 deletions

View File

@ -88,7 +88,7 @@ RES=res
##-- objects putty puttytel ##-- objects putty puttytel
GOBJS1 = window.$(OBJ) windlg.$(OBJ) winctrls.$(OBJ) terminal.$(OBJ) 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 ##-- objects putty puttytel plink
LOBJS1 = telnet.$(OBJ) raw.$(OBJ) rlogin.$(OBJ) ldisc.$(OBJ) winnet.$(OBJ) LOBJS1 = telnet.$(OBJ) raw.$(OBJ) rlogin.$(OBJ) ldisc.$(OBJ) winnet.$(OBJ)
##-- objects putty plink ##-- objects putty plink
@ -96,13 +96,13 @@ POBJS = be_all.$(OBJ)
##-- objects puttytel ##-- objects puttytel
TOBJS = be_nossh.$(OBJ) TOBJS = be_nossh.$(OBJ)
##-- objects plink ##-- objects plink
PLOBJS = plink.$(OBJ) PLOBJS = plink.$(OBJ) logging.$(OBJ)
##-- objects pscp ##-- objects pscp
SOBJS = scp.$(OBJ) winnet.$(OBJ) be_none.$(OBJ) wildcard.$(OBJ) SOBJS = scp.$(OBJ) winnet.$(OBJ) be_none.$(OBJ) wildcard.$(OBJ)
##-- objects psftp ##-- objects psftp
FOBJS = psftp.$(OBJ) winnet.$(OBJ) be_none.$(OBJ) FOBJS = psftp.$(OBJ) winnet.$(OBJ) be_none.$(OBJ)
##-- objects pscp psftp ##-- objects pscp psftp
SFOBJS = sftp.$(OBJ) int64.$(OBJ) SFOBJS = sftp.$(OBJ) int64.$(OBJ) logging.$(OBJ)
##-- objects putty puttytel pscp psftp plink ##-- objects putty puttytel pscp psftp plink
MOBJS = misc.$(OBJ) version.$(OBJ) winstore.$(OBJ) settings.$(OBJ) MOBJS = misc.$(OBJ) version.$(OBJ) winstore.$(OBJ) settings.$(OBJ)
MOBJ2 = tree234.$(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 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 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 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 test.$(OBJ): test.c network.h int64.h puttymem.h ssh.h
tree234.$(OBJ): tree234.c tree234.h tree234.$(OBJ): tree234.c tree234.h
unicode.$(OBJ): unicode.c network.h misc.h puttymem.h putty.h unicode.$(OBJ): unicode.c network.h misc.h puttymem.h putty.h

View File

@ -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 \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 else can replay the session later in slow motion and watch to see
what went wrong. 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} \S{config-logfilename} \q{Log file name}
\cfg{winhelp-topic}{logging.filename} \cfg{winhelp-topic}{logging.filename}

177
logging.c Normal file
View File

@ -0,0 +1,177 @@
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <assert.h>
#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" : "<ukwn>"));
/* 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":<hostname> "&&":&
*/
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';
}

38
plink.c
View File

@ -162,6 +162,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. * Warn about the obsolescent key file format.
*/ */

38
psftp.c
View File

@ -1455,6 +1455,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. * Warn about the obsolescent key file format.
*/ */

10
putty.h
View File

@ -130,7 +130,8 @@ GLOBAL unsigned char unitab_ctrl[256];
#define LGXF_ASK -1 /* existing logfile ask */ #define LGXF_ASK -1 /* existing logfile ask */
#define LGTYP_NONE 0 /* logmode: no logging */ #define LGTYP_NONE 0 /* logmode: no logging */
#define LGTYP_ASCII 1 /* logmode: pure ascii */ #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; GLOBAL char *logfile;
/* /*
@ -485,6 +486,13 @@ void logfopen(void);
void logfclose(void); void logfclose(void);
void term_copyall(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. * Exports from raw.c.
*/ */

38
scp.c
View File

@ -226,6 +226,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. * Warn about the obsolescent key file format.
*/ */

176
ssh.c
View File

@ -15,9 +15,6 @@
#define TRUE 1 #define TRUE 1
#endif #endif
/* uncomment this for packet level debugging */
/* #define DUMP_PACKETS */
#define logevent(s) { logevent(s); \ #define logevent(s) { logevent(s); \
if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) \ if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) \
{ fprintf(stderr, "%s\n", s); fflush(stderr); } } { fprintf(stderr, "%s\n", s); fflush(stderr); } }
@ -112,6 +109,17 @@
#define SSH2_MSG_CHANNEL_SUCCESS 99 /* 0x63 */ #define SSH2_MSG_CHANNEL_SUCCESS 99 /* 0x63 */
#define SSH2_MSG_CHANNEL_FAILURE 100 /* 0x64 */ #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_HOST_NOT_ALLOWED_TO_CONNECT 1 /* 0x1 */
#define SSH2_DISCONNECT_PROTOCOL_ERROR 2 /* 0x2 */ #define SSH2_DISCONNECT_PROTOCOL_ERROR 2 /* 0x2 */
#define SSH2_DISCONNECT_KEY_EXCHANGE_FAILED 3 /* 0x3 */ #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_SSH2_HMAC 2
#define BUG_NEEDS_SSH1_PLAIN_PASSWORD 4 #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) \ #define GET_32BIT(cp) \
(((unsigned long)(unsigned char)(cp)[0] << 24) | \ (((unsigned long)(unsigned char)(cp)[0] << 24) | \
@ -626,10 +725,6 @@ static int ssh1_rdpkt(unsigned char **data, int *datalen)
if (cipher) if (cipher)
cipher->decrypt(pktin.data, st->biglen); 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->realcrc = crc32(pktin.data, st->biglen - 4);
st->gotcrc = GET_32BIT(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) { if (ssh1_compressing) {
unsigned char *decompblk; unsigned char *decompblk;
int decomplen; 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, zlib_decompress_block(pktin.body - 1, pktin.length + 1,
&decompblk, &decomplen); &decompblk, &decomplen);
@ -661,12 +752,13 @@ static int ssh1_rdpkt(unsigned char **data, int *datalen)
memcpy(pktin.body - 1, decompblk, decomplen); memcpy(pktin.body - 1, decompblk, decomplen);
sfree(decompblk); sfree(decompblk);
pktin.length = decomplen - 1; 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 || if (pktin.type == SSH1_SMSG_STDOUT_DATA ||
pktin.type == SSH1_SMSG_STDERR_DATA || pktin.type == SSH1_SMSG_STDERR_DATA ||
pktin.type == SSH1_MSG_DEBUG || 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) { if (pktin.type == SSH1_MSG_DEBUG) {
/* log debug message */ /* log debug message */
char buf[80]; char buf[80];
@ -807,11 +897,6 @@ static int ssh2_rdpkt(unsigned char **data, int *datalen)
sccipher->decrypt(pktin.data + st->cipherblk, sccipher->decrypt(pktin.data + st->cipherblk,
st->packetlen - 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. * Check the MAC.
*/ */
@ -844,11 +929,6 @@ static int ssh2_rdpkt(unsigned char **data, int *datalen)
} }
pktin.length = 5 + newlen; pktin.length = 5 + newlen;
memcpy(pktin.data + 5, newpayload, newlen); memcpy(pktin.data + 5, newpayload, newlen);
#ifdef DUMP_PACKETS
debug(("Post-decompression payload:\n"));
dmemdump(pktin.data + 5, newlen);
#endif
sfree(newpayload); sfree(newpayload);
} }
} }
@ -856,6 +936,9 @@ static int ssh2_rdpkt(unsigned char **data, int *datalen)
pktin.savedpos = 6; pktin.savedpos = 6;
pktin.type = pktin.data[5]; 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) if (pktin.type == SSH2_MSG_IGNORE || pktin.type == SSH2_MSG_DEBUG)
goto next_packet; /* FIXME: print DEBUG message */ goto next_packet; /* FIXME: print DEBUG message */
@ -930,13 +1013,12 @@ static int s_wrpkt_prepare(void)
pktout.body[-1] = pktout.type; pktout.body[-1] = pktout.type;
log_packet(PKT_OUTGOING, pktout.type, ssh1_pkt_type(pktout.type),
pktout.body, pktout.length);
if (ssh1_compressing) { if (ssh1_compressing) {
unsigned char *compblk; unsigned char *compblk;
int complen; 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, zlib_compress_block(pktout.body - 1, pktout.length + 1,
&compblk, &complen); &compblk, &complen);
ssh1_pktout_size(complen - 1); 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 + biglen, crc);
PUT_32BIT(pktout.data, len); PUT_32BIT(pktout.data, len);
#ifdef DUMP_PACKETS
debug(("Sending packet len=%d\n", biglen + 4));
dmemdump(pktout.data, biglen + 4);
#endif
if (cipher) if (cipher)
cipher->encrypt(pktout.data + 4, biglen); cipher->encrypt(pktout.data + 4, biglen);
@ -1221,18 +1299,15 @@ static int ssh2_pkt_construct(void)
int cipherblk, maclen, padding, i; int cipherblk, maclen, padding, i;
static unsigned long outgoing_sequence = 0; 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. * Compress packet payload.
*/ */
{ {
unsigned char *newpayload; unsigned char *newpayload;
int newlen; 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, if (cscomp && cscomp->compress(pktout.data + 5, pktout.length - 5,
&newpayload, &newlen)) { &newpayload, &newlen)) {
pktout.length = 5; pktout.length = 5;
@ -1261,11 +1336,6 @@ static int ssh2_pkt_construct(void)
outgoing_sequence); outgoing_sequence);
outgoing_sequence++; /* whether or not we MACed */ 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) if (cscipher)
cscipher->encrypt(pktout.data, pktout.length + padding); 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) { if (kex == &ssh_diffiehellman_gex) {
logevent("Doing Diffie-Hellman group exchange"); 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 * Work out how big a DH group we will need to allow that
* much data. * 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_init_value = SSH2_MSG_KEX_DH_GEX_INIT;
kex_reply_value = SSH2_MSG_KEX_DH_GEX_REPLY; kex_reply_value = SSH2_MSG_KEX_DH_GEX_REPLY;
} else { } else {
ssh_pkt_ctx |= SSH2_PKTCTX_DHGROUP1;
dh_setup_group1(); dh_setup_group1();
kex_init_value = SSH2_MSG_KEXDH_INIT; kex_init_value = SSH2_MSG_KEXDH_INIT;
kex_reply_value = SSH2_MSG_KEXDH_REPLY; 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 * just in case it succeeds, and (b) so that we know what
* authentication methods we can usefully try next. * authentication methods we can usefully try next.
*/ */
ssh_pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK;
ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST); ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
ssh2_pkt_addstring(username); ssh2_pkt_addstring(username);
ssh2_pkt_addstring("ssh-connection"); /* service requested */ 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; method = 0;
ssh_pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK;
if (!method && can_pubkey && agent_exists() && !tried_agent) { 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; static int authed = FALSE;
void *r; void *r;
ssh_pkt_ctx |= SSH2_PKTCTX_PUBLICKEY;
tried_agent = TRUE; tried_agent = TRUE;
logevent("Pageant is running. Requesting keys."); 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; tried_pubkey_config = TRUE;
ssh_pkt_ctx |= SSH2_PKTCTX_PUBLICKEY;
/* /*
* Try the public key supplied in the configuration. * 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; type = AUTH_TYPE_KEYBOARD_INTERACTIVE;
tried_keyb_inter = TRUE; tried_keyb_inter = TRUE;
ssh_pkt_ctx |= SSH2_PKTCTX_KBDINTER;
ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST); ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
ssh2_pkt_addstring(username); ssh2_pkt_addstring(username);
ssh2_pkt_addstring("ssh-connection"); /* service requested */ 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; type = AUTH_TYPE_KEYBOARD_INTERACTIVE;
tried_keyb_inter = TRUE; tried_keyb_inter = TRUE;
ssh_pkt_ctx |= SSH2_PKTCTX_KBDINTER;
/* We've got packet with that "interactive" info /* We've got packet with that "interactive" info
dump banners, and set its prompt as ours */ 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) { if (!method && can_passwd) {
method = AUTH_PASSWORD; method = AUTH_PASSWORD;
ssh_pkt_ctx |= SSH2_PKTCTX_PASSWORD;
sprintf(pwprompt, "%.90s@%.90s's password: ", username, sprintf(pwprompt, "%.90s@%.90s's password: ", username,
savedhost); savedhost);
need_pw = TRUE; need_pw = TRUE;

View File

@ -206,10 +206,6 @@ static void erase_lots(int, int, int);
static void swap_screen(int); static void swap_screen(int);
static void update_sbar(void); static void update_sbar(void);
static void deselect(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. * 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; 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" : "<ukwn>"));
/* 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":<hostname> "&&":&
*/
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';
}

View File

@ -257,6 +257,7 @@ enum { IDCX_ABOUT =
IDC_LSTATOFF, IDC_LSTATOFF,
IDC_LSTATASCII, IDC_LSTATASCII,
IDC_LSTATRAW, IDC_LSTATRAW,
IDC_LSTATPACKET,
IDC_LGFSTATIC, IDC_LGFSTATIC,
IDC_LGFEDIT, IDC_LGFEDIT,
IDC_LGFBUTTON, IDC_LGFBUTTON,
@ -621,6 +622,7 @@ char *help_context_cmd(int id)
case IDC_LSTATOFF: case IDC_LSTATOFF:
case IDC_LSTATASCII: case IDC_LSTATASCII:
case IDC_LSTATRAW: case IDC_LSTATRAW:
case IDC_LSTATPACKET:
return "JI(`',`logging.main')"; return "JI(`',`logging.main')";
case IDC_LGFSTATIC: case IDC_LGFSTATIC:
case IDC_LGFEDIT: 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_RLLUSEREDIT, cfg.localusername);
SetDlgItemText(hwnd, IDC_LOGEDIT, cfg.username); SetDlgItemText(hwnd, IDC_LOGEDIT, cfg.username);
SetDlgItemText(hwnd, IDC_LGFEDIT, cfg.logfilename); SetDlgItemText(hwnd, IDC_LGFEDIT, cfg.logfilename);
CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATRAW, CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATPACKET,
cfg.logtype == 0 ? IDC_LSTATOFF : cfg.logtype == LGTYP_NONE ? IDC_LSTATOFF :
cfg.logtype == 1 ? IDC_LSTATASCII : IDC_LSTATRAW); cfg.logtype == LGTYP_ASCII ? IDC_LSTATASCII :
cfg.logtype == LGTYP_DEBUG ? IDC_LSTATRAW :
IDC_LSTATPACKET);
CheckRadioButton(hwnd, IDC_LSTATXOVR, IDC_LSTATXASK, CheckRadioButton(hwnd, IDC_LSTATXOVR, IDC_LSTATXASK,
cfg.logxfovr == LGXF_OVR ? IDC_LSTATXOVR : cfg.logxfovr == LGXF_OVR ? IDC_LSTATXOVR :
cfg.logxfovr == LGXF_ASK ? IDC_LSTATXASK : cfg.logxfovr == LGXF_ASK ? IDC_LSTATXASK :
@ -1254,7 +1258,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
} }
if (panel == loggingpanelstart) { if (panel == loggingpanelstart) {
/* The Logging panel. Accelerators used: [acgo] tplfwe */ /* The Logging panel. Accelerators used: [acgo] tplsfwe */
struct ctlpos cp; struct ctlpos cp;
ctlposinit(&cp, hwnd, 80, 3, 13); ctlposinit(&cp, hwnd, 80, 3, 13);
bartitle(&cp, "Options controlling session logging", bartitle(&cp, "Options controlling session logging",
@ -1264,7 +1268,9 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
"Session logging:", IDC_LSTATSTATIC, "Session logging:", IDC_LSTATSTATIC,
"Logging &turned off completely", IDC_LSTATOFF, "Logging &turned off completely", IDC_LSTATOFF,
"Log &printable output only", IDC_LSTATASCII, "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:", editbutton(&cp, "Log &file name:",
IDC_LGFSTATIC, IDC_LGFEDIT, "Bro&wse...", IDC_LGFSTATIC, IDC_LGFEDIT, "Bro&wse...",
IDC_LGFBUTTON); IDC_LGFBUTTON);
@ -2608,14 +2614,17 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
case IDC_LSTATOFF: case IDC_LSTATOFF:
case IDC_LSTATASCII: case IDC_LSTATASCII:
case IDC_LSTATRAW: case IDC_LSTATRAW:
case IDC_LSTATPACKET:
if (HIWORD(wParam) == BN_CLICKED || if (HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED) { HIWORD(wParam) == BN_DOUBLECLICKED) {
if (IsDlgButtonChecked(hwnd, IDC_LSTATOFF)) if (IsDlgButtonChecked(hwnd, IDC_LSTATOFF))
cfg.logtype = 0; cfg.logtype = LGTYP_NONE;
if (IsDlgButtonChecked(hwnd, IDC_LSTATASCII)) if (IsDlgButtonChecked(hwnd, IDC_LSTATASCII))
cfg.logtype = 1; cfg.logtype = LGTYP_ASCII;
if (IsDlgButtonChecked(hwnd, IDC_LSTATRAW)) if (IsDlgButtonChecked(hwnd, IDC_LSTATRAW))
cfg.logtype = 2; cfg.logtype = LGTYP_DEBUG;
if (IsDlgButtonChecked(hwnd, IDC_LSTATPACKET))
cfg.logtype = LGTYP_PACKETS;
} }
break; break;
case IDC_LSTATXASK: case IDC_LSTATXASK:

View File

@ -632,17 +632,17 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
*/ */
set_input_locale(GetKeyboardLayout(0)); set_input_locale(GetKeyboardLayout(0));
/*
* Open the initial log file if there is one.
*/
logfopen();
/* /*
* Finally show the window! * Finally show the window!
*/ */
ShowWindow(hwnd, show); ShowWindow(hwnd, show);
SetForegroundWindow(hwnd); SetForegroundWindow(hwnd);
/*
* Open the initial log file if there is one.
*/
logfopen();
/* /*
* Set the palette up. * Set the palette up.
*/ */