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:
parent
789bb1e727
commit
3ed0d44f16
7
Makefile
7
Makefile
@ -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
|
||||||
|
@ -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
177
logging.c
Normal 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
38
plink.c
@ -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
38
psftp.c
@ -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
10
putty.h
@ -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
38
scp.c
@ -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
176
ssh.c
@ -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;
|
||||||
|
139
terminal.c
139
terminal.c
@ -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';
|
|
||||||
}
|
|
||||||
|
25
windlg.c
25
windlg.c
@ -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:
|
||||||
|
10
window.c
10
window.c
@ -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.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user