diff --git a/config.c b/config.c index 146fb58b9..cbf31698e 100644 --- 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. */ diff --git a/doc/config.but b/doc/config.but index 2556a3878..8a773ef23 100644 --- a/doc/config.but +++ b/doc/config.but @@ -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 diff --git a/logging.c b/logging.c index 5302998fe..808e429fe 100644 --- 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 b12429f51..93a39e4b7 100644 --- 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 diff --git a/settings.c b/settings.c index a5f2e4489..679fab151 100644 --- a/settings.c +++ b/settings.c @@ -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 5b5a6be79..e8d243133 100644 --- 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 @@ -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; diff --git a/winhelp.h b/winhelp.h index 5271f9243..6b7ca242c 100644 --- 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"