##-- 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
##-- 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)
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
-\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
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}
--- /dev/null
+#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';
+}
}
/*
+ * 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)
}
/*
+ * 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)
#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;
/*
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.
*/
}
/*
+ * 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)
#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); } }
#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 */
#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) | \
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);
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);
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 ||
}
}
- pktin.type = pktin.body[-1];
-
if (pktin.type == SSH1_MSG_DEBUG) {
/* log debug message */
char buf[80];
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.
*/
}
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);
}
}
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 */
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);
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);
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;
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);
*/
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.
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;
* 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 */
}
method = 0;
+ ssh_pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK;
if (!method && can_pubkey && agent_exists() && !tried_agent) {
/*
static int authed = FALSE;
void *r;
+ ssh_pkt_ctx |= SSH2_PKTCTX_PUBLICKEY;
+
tried_agent = TRUE;
logevent("Pageant is running. Requesting keys.");
tried_pubkey_config = TRUE;
+ ssh_pkt_ctx |= SSH2_PKTCTX_PUBLICKEY;
+
/*
* Try the public key supplied in the configuration.
*
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 */
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 */
{
if (!method && can_passwd) {
method = AUTH_PASSWORD;
+ ssh_pkt_ctx |= SSH2_PKTCTX_PASSWORD;
sprintf(pwprompt, "%.90s@%.90s's password: ", username,
savedhost);
need_pw = TRUE;
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.
*/
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';
-}
IDC_LSTATOFF,
IDC_LSTATASCII,
IDC_LSTATRAW,
+ IDC_LSTATPACKET,
IDC_LGFSTATIC,
IDC_LGFEDIT,
IDC_LGFBUTTON,
case IDC_LSTATOFF:
case IDC_LSTATASCII:
case IDC_LSTATRAW:
+ case IDC_LSTATPACKET:
return "JI(`',`logging.main')";
case IDC_LGFSTATIC:
case IDC_LGFEDIT:
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 :
}
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",
"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);
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:
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.