1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-03 20:42:48 -05:00

`ssh-log-pw-blank': known password fields are now omitted from SSH packet logs

by default (although they can be included). There's also an option to remove
session data, which is good both for privacy and for reducing the size of
logfiles.

[originally from svn r4593]
This commit is contained in:
Jacob Nevins
2004-10-02 00:33:27 +00:00
parent fb92f118bd
commit e375ba107d
7 changed files with 311 additions and 39 deletions

190
ssh.c
View File

@ -267,7 +267,13 @@ static char *ssh2_pkt_type(int pkt_ctx, int type)
(cp)[2] = (unsigned char)((value) >> 8); \
(cp)[3] = (unsigned char)(value); }
enum { PKT_END, PKT_INT, PKT_CHAR, PKT_DATA, PKT_STR, PKT_BIGNUM };
/* Enumeration values for fields in SSH-1 packets */
enum {
PKT_END, PKT_INT, PKT_CHAR, PKT_DATA, PKT_STR, PKT_BIGNUM,
/* These values are for communicating relevant semantics of
* fields to the packet logging code. */
PKTT_OTHER, PKTT_PASSWORD, PKTT_DATA
};
/*
* Coroutine mechanics for the sillier bits of the code. If these
@ -597,6 +603,13 @@ struct ssh_tag {
unsigned char *deferred_send_data;
int deferred_len, deferred_size;
/*
* State associated with packet logging
*/
int pktout_logmode;
int pktout_nblanks;
struct logblank_t *pktout_blanks;
/*
* Gross hack: pscp will try to start SFTP but fall back to
* scp1 if that fails. This variable is the means by which
@ -684,6 +697,25 @@ static void logeventf(Ssh ssh, const char *fmt, ...)
sfree(text); \
} while (0)
/* Functions to leave bits out of the SSH packet log file. */
static void dont_log_password(Ssh ssh, int blanktype)
{
if (ssh->cfg.logomitpass)
ssh->pktout_logmode = blanktype;
}
static void dont_log_data(Ssh ssh, int blanktype)
{
if (ssh->cfg.logomitdata)
ssh->pktout_logmode = blanktype;
}
static void end_log_omission(Ssh ssh)
{
ssh->pktout_logmode = PKTLOG_EMIT;
}
static int ssh_channelcmp(void *av, void *bv)
{
struct ssh_channel *a = (struct ssh_channel *) av;
@ -898,11 +930,34 @@ static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
ssh->pktin.type = ssh->pktin.body[-1];
if (ssh->logctx)
/*
* Log incoming packet, possibly omitting sensitive fields.
*/
if (ssh->logctx) {
int nblanks = 0;
struct logblank_t blank;
if (ssh->cfg.logomitdata) {
int do_blank = FALSE, blank_prefix = 0;
/* "Session data" packets - omit the data field */
if ((ssh->pktin.type == SSH1_SMSG_STDOUT_DATA) ||
(ssh->pktin.type == SSH1_SMSG_STDERR_DATA)) {
do_blank = TRUE; blank_prefix = 0;
} else if (ssh->pktin.type == SSH1_MSG_CHANNEL_DATA) {
do_blank = TRUE; blank_prefix = 4;
}
if (do_blank) {
blank.offset = blank_prefix;
blank.len = ssh->pktin.length;
blank.type = PKTLOG_OMIT;
nblanks = 1;
}
}
log_packet(ssh->logctx,
PKT_INCOMING, ssh->pktin.type,
ssh1_pkt_type(ssh->pktin.type),
ssh->pktin.body, ssh->pktin.length);
ssh->pktin.body, ssh->pktin.length,
nblanks, &blank);
}
if (ssh->pktin.type == SSH1_SMSG_STDOUT_DATA ||
ssh->pktin.type == SSH1_SMSG_STDERR_DATA ||
@ -1079,10 +1134,32 @@ static int ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
ssh->pktin.body = ssh->pktin.data;
ssh->pktin.type = ssh->pktin.data[5];
if (ssh->logctx)
/*
* Log incoming packet, possibly omitting sensitive fields.
*/
if (ssh->logctx) {
int nblanks = 0;
struct logblank_t blank;
if (ssh->cfg.logomitdata) {
int do_blank = FALSE, blank_prefix = 0;
/* "Session data" packets - omit the data field */
if (ssh->pktin.type == SSH2_MSG_CHANNEL_DATA) {
do_blank = TRUE; blank_prefix = 4;
} else if (ssh->pktin.type == SSH2_MSG_CHANNEL_EXTENDED_DATA) {
do_blank = TRUE; blank_prefix = 8;
}
if (do_blank) {
blank.offset = blank_prefix;
blank.len = (ssh->pktin.length-6) - blank_prefix;
blank.type = PKTLOG_OMIT;
nblanks = 1;
}
}
log_packet(ssh->logctx, PKT_INCOMING, ssh->pktin.type,
ssh2_pkt_type(ssh->pkt_ctx, ssh->pktin.type),
ssh->pktin.data+6, ssh->pktin.length-6);
ssh->pktin.data+6, ssh->pktin.length-6,
nblanks, &blank);
}
switch (ssh->pktin.type) {
/*
@ -1215,6 +1292,9 @@ static void s_wrpkt_start(Ssh ssh, int type, int len)
{
ssh1_pktout_size(ssh, len);
ssh->pktout.type = type;
/* Initialise log omission state */
ssh->pktout_nblanks = 0;
ssh->pktout_blanks = NULL;
}
static int s_wrpkt_prepare(Ssh ssh)
@ -1237,7 +1317,10 @@ static int s_wrpkt_prepare(Ssh ssh)
if (ssh->logctx)
log_packet(ssh->logctx, PKT_OUTGOING, ssh->pktout.type,
ssh1_pkt_type(ssh->pktout.type),
ssh->pktout.body, ssh->pktout.length);
ssh->pktout.body, ssh->pktout.length,
ssh->pktout_nblanks, ssh->pktout_blanks);
sfree(ssh->pktout_blanks); ssh->pktout_blanks = NULL;
ssh->pktout_nblanks = 0;
if (ssh->v1_compressing) {
unsigned char *compblk;
@ -1324,6 +1407,11 @@ static void construct_packet(Ssh ssh, int pkttype, va_list ap1, va_list ap2)
bn = va_arg(ap1, Bignum);
pktlen += ssh1_bignum_length(bn);
break;
case PKTT_PASSWORD:
case PKTT_DATA:
case PKTT_OTHER:
/* ignore this pass */
break;
default:
assert(0);
}
@ -1333,34 +1421,58 @@ static void construct_packet(Ssh ssh, int pkttype, va_list ap1, va_list ap2)
p = ssh->pktout.body;
while ((argtype = va_arg(ap2, int)) != PKT_END) {
int offset = p - ssh->pktout.body, len = 0;
switch (argtype) {
/* Actual fields in the packet */
case PKT_INT:
argint = va_arg(ap2, int);
PUT_32BIT(p, argint);
p += 4;
len = 4;
break;
case PKT_CHAR:
argchar = (unsigned char) va_arg(ap2, int);
*p = argchar;
p++;
len = 1;
break;
case PKT_DATA:
argp = va_arg(ap2, unsigned char *);
arglen = va_arg(ap2, int);
memcpy(p, argp, arglen);
p += arglen;
len = arglen;
break;
case PKT_STR:
argp = va_arg(ap2, unsigned char *);
arglen = strlen((char *)argp);
PUT_32BIT(p, arglen);
memcpy(p + 4, argp, arglen);
p += 4 + arglen;
len = arglen + 4;
break;
case PKT_BIGNUM:
bn = va_arg(ap2, Bignum);
p += ssh1_write_bignum(p, bn);
len = ssh1_write_bignum(p, bn);
break;
/* Tokens for modifications to packet logging */
case PKTT_PASSWORD:
dont_log_password(ssh, PKTLOG_BLANK);
break;
case PKTT_DATA:
dont_log_data(ssh, PKTLOG_OMIT);
break;
case PKTT_OTHER:
end_log_omission(ssh);
break;
}
p += len;
/* Deal with logfile omission, if required. */
if (len && (ssh->pktout_logmode != PKTLOG_EMIT)) {
ssh->pktout_nblanks++;
ssh->pktout_blanks = sresize(ssh->pktout_blanks,
ssh->pktout_nblanks,
struct logblank_t);
ssh->pktout_blanks[ssh->pktout_nblanks-1].offset = offset;
ssh->pktout_blanks[ssh->pktout_nblanks-1].len = len;
ssh->pktout_blanks[ssh->pktout_nblanks-1].type =
ssh->pktout_logmode;
}
}
}
@ -1439,6 +1551,15 @@ static void ssh2_pkt_ensure(Ssh ssh, int length)
}
static void ssh2_pkt_adddata(Ssh ssh, void *data, int len)
{
if (ssh->pktout_logmode != PKTLOG_EMIT) {
ssh->pktout_nblanks++;
ssh->pktout_blanks = sresize(ssh->pktout_blanks, ssh->pktout_nblanks,
struct logblank_t);
ssh->pktout_blanks[ssh->pktout_nblanks-1].offset =
ssh->pktout.length - 6;
ssh->pktout_blanks[ssh->pktout_nblanks-1].len = len;
ssh->pktout_blanks[ssh->pktout_nblanks-1].type = ssh->pktout_logmode;
}
ssh->pktout.length += len;
ssh2_pkt_ensure(ssh, ssh->pktout.length);
memcpy(ssh->pktout.data + ssh->pktout.length - len, data, len);
@ -1450,6 +1571,7 @@ static void ssh2_pkt_addbyte(Ssh ssh, unsigned char byte)
static void ssh2_pkt_init(Ssh ssh, int pkt_type)
{
ssh->pktout.length = 5;
ssh->pktout_nblanks = 0; ssh->pktout_blanks = NULL;
ssh2_pkt_addbyte(ssh, (unsigned char) pkt_type);
}
static void ssh2_pkt_addbool(Ssh ssh, unsigned char value)
@ -1523,7 +1645,10 @@ static int ssh2_pkt_construct(Ssh ssh)
if (ssh->logctx)
log_packet(ssh->logctx, PKT_OUTGOING, ssh->pktout.data[5],
ssh2_pkt_type(ssh->pkt_ctx, ssh->pktout.data[5]),
ssh->pktout.data + 6, ssh->pktout.length - 6);
ssh->pktout.data + 6, ssh->pktout.length - 6,
ssh->pktout_nblanks, ssh->pktout_blanks);
sfree(ssh->pktout_blanks); ssh->pktout_blanks = NULL;
ssh->pktout_nblanks = 0;
/*
* Compress packet payload.
@ -2376,8 +2501,10 @@ static void ssh_agentf_callback(void *cv, void *reply, int replylen)
} else {
send_packet(ssh, SSH1_MSG_CHANNEL_DATA,
PKT_INT, c->remoteid,
PKTT_DATA,
PKT_INT, replylen,
PKT_DATA, sentreply, replylen,
PKTT_OTHER,
PKT_END);
}
if (reply)
@ -3154,10 +3281,11 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
randomstr = snewn(top + 1, char);
for (i = bottom; i <= top; i++) {
if (i == pwlen)
if (i == pwlen) {
defer_packet(ssh, s->pwpkt_type,
PKT_STR, s->password, PKT_END);
else {
PKTT_PASSWORD, PKT_STR, s->password,
PKTT_OTHER, PKT_END);
} else {
for (j = 0; j < i; j++) {
do {
randomstr[j] = random_byte();
@ -3194,8 +3322,9 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
ss = s->password;
}
logevent("Sending length-padded password");
send_packet(ssh, s->pwpkt_type, PKT_INT, len,
PKT_DATA, ss, len, PKT_END);
send_packet(ssh, s->pwpkt_type, PKTT_PASSWORD,
PKT_INT, len, PKT_DATA, ss, len,
PKTT_OTHER, PKT_END);
} else {
/*
* The server has _both_
@ -3206,11 +3335,14 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
int len;
len = strlen(s->password);
logevent("Sending unpadded password");
send_packet(ssh, s->pwpkt_type, PKT_INT, len,
PKT_DATA, s->password, len, PKT_END);
send_packet(ssh, s->pwpkt_type,
PKTT_PASSWORD, PKT_INT, len,
PKT_DATA, s->password, len,
PKTT_OTHER, PKT_END);
}
} else {
send_packet(ssh, s->pwpkt_type, PKT_STR, s->password, PKT_END);
send_packet(ssh, s->pwpkt_type, PKTT_PASSWORD,
PKT_STR, s->password, PKTT_OTHER, PKT_END);
}
}
logevent("Sent password");
@ -3282,7 +3414,9 @@ int sshfwd_write(struct ssh_channel *c, char *buf, int len)
if (ssh->version == 1) {
send_packet(ssh, SSH1_MSG_CHANNEL_DATA,
PKT_INT, c->remoteid,
PKT_INT, len, PKT_DATA, buf, len, PKT_END);
PKTT_DATA,
PKT_INT, len, PKT_DATA, buf, len,
PKTT_OTHER, PKT_END);
/*
* In SSH1 we can return 0 here - implying that forwarded
* connections are never individually throttled - because
@ -3928,8 +4062,9 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
} else {
while (inlen > 0) {
int len = min(inlen, 512);
send_packet(ssh, SSH1_CMSG_STDIN_DATA,
PKT_INT, len, PKT_DATA, in, len, PKT_END);
send_packet(ssh, SSH1_CMSG_STDIN_DATA, PKTT_DATA,
PKT_INT, len, PKT_DATA, in, len,
PKTT_OTHER, PKT_END);
in += len;
inlen -= len;
}
@ -4573,8 +4708,10 @@ static int ssh2_try_send(struct ssh_channel *c)
len = c->v.v2.remmaxpkt;
ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_DATA);
ssh2_pkt_adduint32(ssh, c->remoteid);
dont_log_data(ssh, PKTLOG_OMIT);
ssh2_pkt_addstring_start(ssh);
ssh2_pkt_addstring_data(ssh, data, len);
end_log_omission(ssh);
ssh2_pkt_send(ssh);
bufchain_consume(&c->v.v2.outbuffer, len);
c->v.v2.remwindow -= len;
@ -5385,8 +5522,10 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
ssh2_pkt_addstring(ssh, "ssh-connection"); /* service requested */
ssh2_pkt_addstring(ssh, "password");
ssh2_pkt_addbool(ssh, FALSE);
dont_log_password(ssh, PKTLOG_BLANK);
ssh2_pkt_addstring(ssh, s->password);
memset(s->password, 0, sizeof(s->password));
end_log_omission(ssh);
ssh2_pkt_defer(ssh);
/*
* We'll include a string that's an exact multiple of the
@ -5430,8 +5569,10 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
ssh2_pkt_adduint32(ssh, s->num_prompts);
}
if (s->need_pw) { /* only add pw if we just got one! */
dont_log_password(ssh, PKTLOG_BLANK);
ssh2_pkt_addstring(ssh, s->password);
memset(s->password, 0, sizeof(s->password));
end_log_omission(ssh);
s->curr_prompt++;
}
if (s->curr_prompt >= s->num_prompts) {
@ -6412,6 +6553,9 @@ static const char *ssh_init(void *frontend_handle, void **backend_handle,
ssh->deferred_send_data = NULL;
ssh->deferred_len = 0;
ssh->deferred_size = 0;
ssh->pktout_logmode = PKTLOG_EMIT;
ssh->pktout_nblanks = 0;
ssh->pktout_blanks = NULL;
ssh->fallback_cmd = 0;
ssh->pkt_ctx = 0;
ssh->x11auth = NULL;