diff --git a/Buildscr b/Buildscr index bc606ca4..466571bc 100644 --- a/Buildscr +++ b/Buildscr @@ -35,7 +35,7 @@ module putty ifeq "$(RELEASE)" "" set Ndate $(!builddate) ifneq "$(Ndate)" "" in . do echo $(Ndate) | perl -pe 's/(....)(..)(..)/$$1-$$2-$$3/' > date ifneq "$(Ndate)" "" read Date date -set Epoch 15641 # update this at every release +set Epoch 15746 # update this at every release ifneq "$(Ndate)" "" in . do echo $(Ndate) | perl -ne 'use Time::Local; /(....)(..)(..)/ and print timegm(0,0,0,$$3,$$2-1,$$1) / 86400 - $(Epoch)' > days ifneq "$(Ndate)" "" read Days days diff --git a/LATEST.VER b/LATEST.VER index f429be05..ceee7dd5 100644 --- a/LATEST.VER +++ b/LATEST.VER @@ -1 +1 @@ -0.65 +0.66 diff --git a/doc/plink.but b/doc/plink.but index 553639e6..889d3b6a 100644 --- a/doc/plink.but +++ b/doc/plink.but @@ -41,7 +41,7 @@ use Plink: \c Z:\sysosd>plink \c Plink: command-line connection utility -\c Release 0.XX +\c Release 0.66 \c Usage: plink [options] [user@]host [command] \c ("host" can also be a PuTTY saved session name) \c Options: diff --git a/doc/pscp.but b/doc/pscp.but index 01b4aacd..89ca90b5 100644 --- a/doc/pscp.but +++ b/doc/pscp.but @@ -39,7 +39,7 @@ use PSCP: \c Z:\owendadmin>pscp \c PuTTY Secure Copy client -\c Release 0.65 +\c Release 0.66 \c Usage: pscp [options] [user@]host:source target \c pscp [options] source [source...] [user@]host:target \c pscp [options] -ls [user@]host:filespec diff --git a/doc/using.but b/doc/using.but index a2d8c271..5448b81a 100644 --- a/doc/using.but +++ b/doc/using.but @@ -953,3 +953,20 @@ DSR/DTR. For example, \cq{-sercfg 19200,8,n,1,N} denotes a baud rate of 19200, 8 data bits, no parity, 1 stop bit and no flow control. + +\S2{using-cmdline-sshlog} \i\c{-sessionlog}, \i\c{-sshlog}, +\i\c{-sshrawlog}: specify session logging + +These options cause the PuTTY network tools to write out a \i{log +file}. Each of them expects a file name as an argument, e.g. +\cq{-sshlog putty.log} causes an SSH packet log to be written to a +file called \cq{putty.log}. The three different options select +different logging modes, all available from the GUI too: + +\b \c{-sessionlog} selects \q{All session output} logging mode. + +\b \c{-sshlog} selects \q{SSH packets} logging mode. + +\b \c{-sshrawlog} selects \q{SSH packets and raw data} logging mode. + +For more information on logging configuration, see \k{config-logging}. diff --git a/logging.c b/logging.c index 563dcded..865fe9b8 100644 --- a/logging.c +++ b/logging.c @@ -164,6 +164,7 @@ void logfopen(void *handle) { struct LogContext *ctx = (struct LogContext *)handle; struct tm tm; + FILE *fp; int mode; /* Prevent repeat calls */ @@ -183,10 +184,10 @@ void logfopen(void *handle) conf_get_str(ctx->conf, CONF_host), conf_get_int(ctx->conf, CONF_port), &tm); - ctx->lgfp = f_open(ctx->currlogfilename, "r", FALSE); /* file already present? */ - if (ctx->lgfp) { + fp = f_open(ctx->currlogfilename, "r", FALSE); /* file already present? */ + if (fp) { int logxfovr = conf_get_int(ctx->conf, CONF_logxfovr); - fclose(ctx->lgfp); + fclose(fp); if (logxfovr != LGXF_ASK) { mode = ((logxfovr == LGXF_OVR) ? 2 : 1); } else diff --git a/ssh.c b/ssh.c index 5d6514b5..1f8a214b 100644 --- a/ssh.c +++ b/ssh.c @@ -364,6 +364,7 @@ static void do_ssh2_authconn(Ssh ssh, const unsigned char *in, int inlen, struct Packet *pktin); static void ssh2_channel_check_close(struct ssh_channel *c); static void ssh_channel_destroy(struct ssh_channel *c); +static void ssh2_msg_something_unimplemented(Ssh ssh, struct Packet *pktin); /* * Buffer management constants. There are several of these for @@ -1834,6 +1835,15 @@ static struct Packet *ssh2_rdpkt(Ssh ssh, const unsigned char **data, } } + /* + * RFC 4253 doesn't explicitly say that completely empty packets + * with no type byte are forbidden, so treat them as deserving + * an SSH_MSG_UNIMPLEMENTED. + */ + if (st->pktin->length <= 5) { /* == 5 we hope, but robustness */ + ssh2_msg_something_unimplemented(ssh, st->pktin); + crStop(NULL); + } /* * pktin->body and pktin->length should identify the semantic * content of the packet, excluding the initial type byte. diff --git a/sshrsa.c b/sshrsa.c index 850204c7..e565a64a 100644 --- a/sshrsa.c +++ b/sshrsa.c @@ -773,6 +773,8 @@ static int rsa2_pubkey_bits(const struct ssh_signkey *self, int ret; rsa = rsa2_newkey(self, (const char *) blob, len); + if (!rsa) + return -1; ret = bignum_bitcount(rsa->modulus); rsa2_freekey(rsa); diff --git a/terminal.c b/terminal.c index ca47c833..c5fdeeb0 100644 --- a/terminal.c +++ b/terminal.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -2343,7 +2344,7 @@ static void check_boundary(Terminal *term, int x, int y) termline *ldata; /* Validate input coordinates, just in case. */ - if (x == 0 || x > term->cols) + if (x <= 0 || x > term->cols) return; ldata = scrlineptr(y); @@ -3493,8 +3494,15 @@ static void term_out(Terminal *term) if (term->esc_nargs <= ARGS_MAX) { if (term->esc_args[term->esc_nargs - 1] == ARG_DEFAULT) term->esc_args[term->esc_nargs - 1] = 0; - term->esc_args[term->esc_nargs - 1] = - 10 * term->esc_args[term->esc_nargs - 1] + c - '0'; + if (term->esc_args[term->esc_nargs - 1] <= + UINT_MAX / 10 && + term->esc_args[term->esc_nargs - 1] * 10 <= + UINT_MAX - c - '0') + term->esc_args[term->esc_nargs - 1] = + 10 * term->esc_args[term->esc_nargs - 1] + + c - '0'; + else + term->esc_args[term->esc_nargs - 1] = UINT_MAX; } term->termstate = SEEN_CSI; } else if (c == ';') { @@ -3510,8 +3518,10 @@ static void term_out(Terminal *term) term->esc_query = c; term->termstate = SEEN_CSI; } else +#define CLAMP(arg, lim) ((arg) = ((arg) > (lim)) ? (lim) : (arg)) switch (ANSI(c, term->esc_query)) { case 'A': /* CUU: move up N lines */ + CLAMP(term->esc_args[0], term->rows); move(term, term->curs.x, term->curs.y - def(term->esc_args[0], 1), 1); seen_disp_event(term); @@ -3520,6 +3530,7 @@ static void term_out(Terminal *term) compatibility(ANSI); /* FALLTHROUGH */ case 'B': /* CUD: Cursor down */ + CLAMP(term->esc_args[0], term->rows); move(term, term->curs.x, term->curs.y + def(term->esc_args[0], 1), 1); seen_disp_event(term); @@ -3535,23 +3546,27 @@ static void term_out(Terminal *term) compatibility(ANSI); /* FALLTHROUGH */ case 'C': /* CUF: Cursor right */ + CLAMP(term->esc_args[0], term->cols); move(term, term->curs.x + def(term->esc_args[0], 1), term->curs.y, 1); seen_disp_event(term); break; case 'D': /* CUB: move left N cols */ + CLAMP(term->esc_args[0], term->cols); move(term, term->curs.x - def(term->esc_args[0], 1), term->curs.y, 1); seen_disp_event(term); break; case 'E': /* CNL: move down N lines and CR */ compatibility(ANSI); + CLAMP(term->esc_args[0], term->rows); move(term, 0, term->curs.y + def(term->esc_args[0], 1), 1); seen_disp_event(term); break; case 'F': /* CPL: move up N lines and CR */ compatibility(ANSI); + CLAMP(term->esc_args[0], term->rows); move(term, 0, term->curs.y - def(term->esc_args[0], 1), 1); seen_disp_event(term); @@ -3559,12 +3574,14 @@ static void term_out(Terminal *term) case 'G': /* CHA */ case '`': /* HPA: set horizontal posn */ compatibility(ANSI); + CLAMP(term->esc_args[0], term->cols); move(term, def(term->esc_args[0], 1) - 1, term->curs.y, 0); seen_disp_event(term); break; case 'd': /* VPA: set vertical posn */ compatibility(ANSI); + CLAMP(term->esc_args[0], term->rows); move(term, term->curs.x, ((term->dec_om ? term->marg_t : 0) + def(term->esc_args[0], 1) - 1), @@ -3575,6 +3592,8 @@ static void term_out(Terminal *term) case 'f': /* HVP: set horz and vert posns at once */ if (term->esc_nargs < 2) term->esc_args[1] = ARG_DEFAULT; + CLAMP(term->esc_args[0], term->rows); + CLAMP(term->esc_args[1], term->cols); move(term, def(term->esc_args[1], 1) - 1, ((term->dec_om ? term->marg_t : 0) + def(term->esc_args[0], 1) - 1), @@ -3610,6 +3629,7 @@ static void term_out(Terminal *term) break; case 'L': /* IL: insert lines */ compatibility(VT102); + CLAMP(term->esc_args[0], term->rows); if (term->curs.y <= term->marg_b) scroll(term, term->curs.y, term->marg_b, -def(term->esc_args[0], 1), FALSE); @@ -3617,6 +3637,7 @@ static void term_out(Terminal *term) break; case 'M': /* DL: delete lines */ compatibility(VT102); + CLAMP(term->esc_args[0], term->rows); if (term->curs.y <= term->marg_b) scroll(term, term->curs.y, term->marg_b, def(term->esc_args[0], 1), @@ -3626,11 +3647,13 @@ static void term_out(Terminal *term) case '@': /* ICH: insert chars */ /* XXX VTTEST says this is vt220, vt510 manual says vt102 */ compatibility(VT102); + CLAMP(term->esc_args[0], term->cols); insch(term, def(term->esc_args[0], 1)); seen_disp_event(term); break; case 'P': /* DCH: delete chars */ compatibility(VT102); + CLAMP(term->esc_args[0], term->cols); insch(term, -def(term->esc_args[0], 1)); seen_disp_event(term); break; @@ -3708,6 +3731,8 @@ static void term_out(Terminal *term) compatibility(VT100); if (term->esc_nargs <= 2) { int top, bot; + CLAMP(term->esc_args[0], term->rows); + CLAMP(term->esc_args[1], term->rows); top = def(term->esc_args[0], 1) - 1; bot = (term->esc_nargs <= 1 || term->esc_args[1] == 0 ? @@ -4063,6 +4088,7 @@ static void term_out(Terminal *term) } break; case 'S': /* SU: Scroll up */ + CLAMP(term->esc_args[0], term->rows); compatibility(SCOANSI); scroll(term, term->marg_t, term->marg_b, def(term->esc_args[0], 1), TRUE); @@ -4070,6 +4096,7 @@ static void term_out(Terminal *term) seen_disp_event(term); break; case 'T': /* SD: Scroll down */ + CLAMP(term->esc_args[0], term->rows); compatibility(SCOANSI); scroll(term, term->marg_t, term->marg_b, -def(term->esc_args[0], 1), TRUE); @@ -4112,6 +4139,7 @@ static void term_out(Terminal *term) /* XXX VTTEST says this is vt220, vt510 manual * says vt100 */ compatibility(ANSIMIN); + CLAMP(term->esc_args[0], term->cols); { int n = def(term->esc_args[0], 1); pos cursplus; @@ -4145,6 +4173,7 @@ static void term_out(Terminal *term) break; case 'Z': /* CBT */ compatibility(OTHER); + CLAMP(term->esc_args[0], term->cols); { int i = def(term->esc_args[0], 1); pos old_curs = term->curs; @@ -4205,7 +4234,7 @@ static void term_out(Terminal *term) break; case ANSI('F', '='): /* set normal foreground */ compatibility(SCOANSI); - if (term->esc_args[0] >= 0 && term->esc_args[0] < 16) { + if (term->esc_args[0] < 16) { long colour = (sco2ansicolour[term->esc_args[0] & 0x7] | (term->esc_args[0] & 0x8)) << @@ -4219,7 +4248,7 @@ static void term_out(Terminal *term) break; case ANSI('G', '='): /* set normal background */ compatibility(SCOANSI); - if (term->esc_args[0] >= 0 && term->esc_args[0] < 16) { + if (term->esc_args[0] < 16) { long colour = (sco2ansicolour[term->esc_args[0] & 0x7] | (term->esc_args[0] & 0x8)) << @@ -4343,7 +4372,11 @@ static void term_out(Terminal *term) case '7': case '8': case '9': - term->esc_args[0] = 10 * term->esc_args[0] + c - '0'; + if (term->esc_args[0] <= UINT_MAX / 10 && + term->esc_args[0] * 10 <= UINT_MAX - c - '0') + term->esc_args[0] = 10 * term->esc_args[0] + c - '0'; + else + term->esc_args[0] = UINT_MAX; break; case 'L': /* @@ -4425,7 +4458,11 @@ static void term_out(Terminal *term) case '7': case '8': case '9': - term->esc_args[0] = 10 * term->esc_args[0] + c - '0'; + if (term->esc_args[0] <= UINT_MAX / 10 && + term->esc_args[0] * 10 <= UINT_MAX - c - '0') + term->esc_args[0] = 10 * term->esc_args[0] + c - '0'; + else + term->esc_args[0] = UINT_MAX; break; default: term->termstate = OSC_STRING; diff --git a/terminal.h b/terminal.h index 135ef45a..01d5f57a 100644 --- a/terminal.h +++ b/terminal.h @@ -172,7 +172,7 @@ struct terminal_tag { #define ARGS_MAX 32 /* max # of esc sequence arguments */ #define ARG_DEFAULT 0 /* if an arg isn't specified */ #define def(a,d) ( (a) == ARG_DEFAULT ? (d) : (a) ) - int esc_args[ARGS_MAX]; + unsigned esc_args[ARGS_MAX]; int esc_nargs; int esc_query; #define ANSI(x,y) ((x)+((y)<<8)) diff --git a/windows/putty.iss b/windows/putty.iss index cb84e1ac..67c92d0f 100644 --- a/windows/putty.iss +++ b/windows/putty.iss @@ -13,10 +13,10 @@ [Setup] AppName=PuTTY -AppVerName=PuTTY version 0.65 -VersionInfoTextVersion=Release 0.65 -AppVersion=0.65 -VersionInfoVersion=0.65.0.0 +AppVerName=PuTTY version 0.66 +VersionInfoTextVersion=Release 0.66 +AppVersion=0.66 +VersionInfoVersion=0.66.0.0 AppPublisher=Simon Tatham AppPublisherURL=http://www.chiark.greenend.org.uk/~sgtatham/putty/ AppReadmeFile={app}\README.txt