`ssh-log-pw-blank': known password fields are now omitted from SSH packet logs
authorjacob <jacob@cda61777-01e9-0310-a592-d414129be87e>
Sat, 2 Oct 2004 00:33:27 +0000 (00:33 +0000)
committerjacob <jacob@cda61777-01e9-0310-a592-d414129be87e>
Sat, 2 Oct 2004 00:33:27 +0000 (00:33 +0000)
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.

git-svn-id: svn://svn.tartarus.org/sgt/putty@4593 cda61777-01e9-0310-a592-d414129be87e

config.c
doc/config.but
logging.c
putty.h
settings.c
ssh.c
winhelp.h

index 146fb58..cbf3169 100644 (file)
--- a/config.c
+++ b/config.c
@@ -885,6 +885,18 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
                      "Always append to the end of it", I(LGXF_APN),
                      "Ask the user every time", I(LGXF_ASK), NULL);
 
+    if ((midsession && protocol == PROT_SSH) ||
+       (!midsession && backends[3].name != NULL)) {
+       s = ctrl_getset(b, "Session/Logging", "ssh",
+                       "Options specific to SSH packet logging");
+       ctrl_checkbox(s, "Omit known password fields", 'k',
+                     HELPCTX(logging_ssh_omit_password),
+                     dlg_stdcheckbox_handler, I(offsetof(Config,logomitpass)));
+       ctrl_checkbox(s, "Omit session data", 'd',
+                     HELPCTX(logging_ssh_omit_data),
+                     dlg_stdcheckbox_handler, I(offsetof(Config,logomitdata)));
+    }
+
     /*
      * The Terminal panel.
      */
index 2556a38..8a773ef 100644 (file)
@@ -1,4 +1,4 @@
-\versionid $Id: config.but,v 1.90 2004/09/22 22:15:25 jacob Exp $
+\versionid $Id: config.but,v 1.91 2004/10/02 00:33:27 jacob Exp $
 
 \C{config} Configuring PuTTY
 
@@ -148,8 +148,9 @@ 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!
+password, the password can appear in the log file; see
+\k{config-logssh} for options that may help to remove sensitive
+material from the log file before you send it to anyone else.
 
 \S{config-logfilename} \q{Log file name}
 
@@ -198,6 +199,44 @@ Finally (the default option), you might not want to have any
 automatic behaviour, but to ask the user every time the problem
 comes up.
 
+\S{config-logssh} Options specific to SSH packet logging
+
+These options only apply if SSH packet data is being logged.
+
+The following options allow particularly sensitive portions of
+unencrypted packets to be automatically left out of the log file.
+They are only intended to deter casual nosiness; an attacker could
+glean a lot of useful information from even these obfuscated logs
+(e.g., length of password).
+
+\S2{config-logssh-omitpw} \q{Omit known password fields}
+
+\cfg{winhelp-topic}{logging.ssh.omitpassword}
+
+When checked, password fields are removed from the log of transmitted
+packets. (This includes any user responses to challenge-response
+authentication methods such as \q{keyboard-interactive}.) This does
+not include X11 authentication data if using X11 forwarding.
+
+Note that this will only omit data that PuTTY \e{knows} to be a
+password. However, if you start another login session within your
+PuTTY session, for instance, any password used will appear in the
+clear in the packet log. The next option may be of use to protect
+against this.
+
+This option is enabled by default.
+
+\S2{config-logssh-omitdata} \q{Omit session data}
+
+\cfg{winhelp-topic}{logging.ssh.omitdata}
+
+When checked, all \q{session data} is omitted; this is defined as data
+in terminal sessions and in forwarded channels (TCP, X11, and
+authentication agent). This will usually substantially reduce the size
+of the resulting log file.
+
+This option is disabled by default.
+
 \H{config-terminal} The Terminal panel
 
 The Terminal configuration panel allows you to control the behaviour
index 5302998..808e429 100644 (file)
--- a/logging.c
+++ b/logging.c
@@ -70,12 +70,14 @@ void log_eventlog(void *handle, const char *event)
 
 /*
  * Log an SSH packet.
+ * If n_blanks != 0, blank or omit some parts.
+ * Set of blanking areas must be in increasing order.
  */
 void log_packet(void *handle, int direction, int type,
-               char *texttype, void *data, int len)
+               char *texttype, void *data, int len,
+               int n_blanks, const struct logblank_t *blanks)
 {
     struct LogContext *ctx = (struct LogContext *)handle;
-    int i, j;
     char dumpdata[80], smalldata[5];
 
     if (ctx->cfg.logtype != LGTYP_PACKETS)
@@ -83,21 +85,81 @@ void log_packet(void *handle, int direction, int type,
     if (!ctx->lgfp)
        logfopen(ctx);
     if (ctx->lgfp) {
+       int p = 0, b = 0, omitted = 0;
+       int output_pos = 0; /* NZ if pending output in dumpdata */
+
+       /* Packet header. */
        fprintf(ctx->lgfp, "%s packet type %d / 0x%02x (%s)\r\n",
                direction == PKT_INCOMING ? "Incoming" : "Outgoing",
                type, type, texttype);
-       for (i = 0; i < len; i += 16) {
-           sprintf(dumpdata, "  %08x%*s\r\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 : '.');
+
+       /*
+        * Output a hex/ASCII dump of the packet body, blanking/omitting
+        * parts as specified.
+        */
+       while (p < len) {
+           int blktype;
+
+           /* Move to a current entry in the blanking array. */
+           while ((b < n_blanks) &&
+                  (p >= blanks[b].offset + blanks[b].len))
+               b++;
+           /* Work out what type of blanking to apply to
+            * this byte. */
+           blktype = PKTLOG_EMIT; /* default */
+           if ((b < n_blanks) &&
+               (p >= blanks[b].offset) &&
+               (p < blanks[b].offset + blanks[b].len))
+               blktype = blanks[b].type;
+
+           /* If we're about to stop omitting, it's time to say how
+            * much we omitted. */
+           if ((blktype != PKTLOG_OMIT) && omitted) {
+               fprintf(ctx->lgfp, "  (%d byte%s omitted)\r\n",
+                       omitted, (omitted==1?"":"s"));
+               omitted = 0;
+           }
+
+           /* (Re-)initialise dumpdata as necessary
+            * (start of row, or if we've just stopped omitting) */
+           if (!output_pos && !omitted)
+               sprintf(dumpdata, "  %08x%*s\r\n", p-(p%16), 1+3*16+2+16, "");
+
+           /* Deal with the current byte. */
+           if (blktype == PKTLOG_OMIT) {
+               omitted++;
+           } else {
+               int c;
+               if (blktype == PKTLOG_BLANK) {
+                   c = 'X';
+                   sprintf(smalldata, "XX");
+               } else {  /* PKTLOG_EMIT */
+                   c = ((unsigned char *)data)[p];
+                   sprintf(smalldata, "%02x", c);
+               }
+               dumpdata[10+2+3*(p%16)] = smalldata[0];
+               dumpdata[10+2+3*(p%16)+1] = smalldata[1];
+               dumpdata[10+1+3*16+2+(p%16)] = (isprint(c) ? c : '.');
+               output_pos = (p%16) + 1;
+           }
+
+           p++;
+
+           /* Flush row if necessary */
+           if (((p % 16) == 0) || (p == len) || omitted) {
+               if (output_pos) {
+                   strcpy(dumpdata + 10+1+3*16+2+output_pos, "\r\n");
+                   fputs(dumpdata, ctx->lgfp);
+                   output_pos = 0;
+               }
            }
-           strcpy(dumpdata + 10+1+3*16+2+j, "\r\n");
-           fputs(dumpdata, ctx->lgfp);
+
        }
+
+       /* Tidy up */
+       if (omitted)
+           fprintf(ctx->lgfp, "  (%d byte%s omitted)\r\n",
+                   omitted, (omitted==1?"":"s"));
        fflush(ctx->lgfp);
     }
 }
diff --git a/putty.h b/putty.h
index b12429f..93a39e4 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -425,6 +425,8 @@ struct config_tag {
     Filename logfilename;
     int logtype;
     int logxfovr;
+    int logomitpass;
+    int logomitdata;
     int hide_mouseptr;
     int sunken_edge;
     int window_border;
@@ -658,8 +660,15 @@ void logtraffic(void *logctx, unsigned char c, int logmode);
 void logflush(void *logctx);
 void log_eventlog(void *logctx, const char *string);
 enum { PKT_INCOMING, PKT_OUTGOING };
+enum { PKTLOG_EMIT, PKTLOG_BLANK, PKTLOG_OMIT };
+struct logblank_t {
+    int offset;
+    int len;
+    int type;
+};
 void log_packet(void *logctx, int direction, int type,
-               char *texttype, void *data, int len);
+               char *texttype, void *data, int len,
+               int n_blanks, const struct logblank_t *blanks);
 
 /*
  * Exports from testback.c
index a5f2e44..679fab1 100644 (file)
@@ -167,6 +167,8 @@ void save_open_settings(void *sesskey, int do_host, Config *cfg)
     write_setting_filename(sesskey, "LogFileName", cfg->logfilename);
     write_setting_i(sesskey, "LogType", cfg->logtype);
     write_setting_i(sesskey, "LogFileClash", cfg->logxfovr);
+    write_setting_i(sesskey, "SSHLogOmitPasswords", cfg->logomitpass);
+    write_setting_i(sesskey, "SSHLogOmitData", cfg->logomitdata);
     p = "raw";
     for (i = 0; backends[i].name != NULL; i++)
        if (backends[i].protocol == cfg->protocol) {
@@ -389,6 +391,8 @@ void load_open_settings(void *sesskey, int do_host, Config *cfg)
     gppfile(sesskey, "LogFileName", &cfg->logfilename);
     gppi(sesskey, "LogType", 0, &cfg->logtype);
     gppi(sesskey, "LogFileClash", LGXF_ASK, &cfg->logxfovr);
+    gppi(sesskey, "SSHLogOmitPasswords", 1, &cfg->logomitpass);
+    gppi(sesskey, "SSHLogOmitData", 0, &cfg->logomitdata);
 
     gpps(sesskey, "Protocol", "default", prot, 10);
     cfg->protocol = default_protocol;
diff --git a/ssh.c b/ssh.c
index 5b5a6be..e8d2431 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -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
@@ -598,6 +604,13 @@ struct ssh_tag {
     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
      * scp.c can reach into the SSH code and find out which one it
@@ -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;
index 5271f92..6b7ca24 100644 (file)
--- a/winhelp.h
+++ b/winhelp.h
@@ -13,6 +13,8 @@
 #define WINHELP_CTX_logging_main "logging.main"
 #define WINHELP_CTX_logging_filename "logging.filename"
 #define WINHELP_CTX_logging_exists "logging.exists"
+#define WINHELP_CTX_logging_ssh_omit_password "logging.ssh.omitpassword"
+#define WINHELP_CTX_logging_ssh_omit_data "logging.ssh.omitdata"
 #define WINHELP_CTX_keyboard_backspace "keyboard.backspace"
 #define WINHELP_CTX_keyboard_homeend "keyboard.homeend"
 #define WINHELP_CTX_keyboard_funkeys "keyboard.funkeys"