1 /*
2  * Packet-censoring code for SSH-2, used to identify sensitive fields
3  * like passwords so that the logging system can avoid writing them
4  * into log files.
5  */
6 
7 #include <assert.h>
8 
9 #include "putty.h"
10 #include "ssh.h"
11 
ssh2_censor_packet(const PacketLogSettings * pls,int type,bool sender_is_client,ptrlen pkt,logblank_t * blanks)12 int ssh2_censor_packet(
13     const PacketLogSettings *pls, int type, bool sender_is_client,
14     ptrlen pkt, logblank_t *blanks)
15 {
16     int nblanks = 0;
17     ptrlen str;
18     BinarySource src[1];
19 
20     BinarySource_BARE_INIT_PL(src, pkt);
21 
22     if (pls->omit_data &&
23         (type == SSH2_MSG_CHANNEL_DATA ||
24          type == SSH2_MSG_CHANNEL_EXTENDED_DATA)) {
25         /* "Session data" packets - omit the data string. */
26         get_uint32(src);              /* skip channel id */
27         if (type == SSH2_MSG_CHANNEL_EXTENDED_DATA)
28             get_uint32(src);          /* skip extended data type */
29         str = get_string(src);
30         if (!get_err(src)) {
31             assert(nblanks < MAX_BLANKS);
32             blanks[nblanks].offset = src->pos - str.len;
33             blanks[nblanks].type = PKTLOG_OMIT;
34             blanks[nblanks].len = str.len;
35             nblanks++;
36         }
37     }
38 
39     if (sender_is_client && pls->omit_passwords) {
40         if (type == SSH2_MSG_USERAUTH_REQUEST) {
41             /* If this is a password packet, blank the password(s). */
42             get_string(src);              /* username */
43             get_string(src);              /* service name */
44             str = get_string(src);        /* auth method */
45             if (ptrlen_eq_string(str, "password")) {
46                 get_bool(src);
47                 /* Blank the password field. */
48                 str = get_string(src);
49                 if (!get_err(src)) {
50                     assert(nblanks < MAX_BLANKS);
51                     blanks[nblanks].offset = src->pos - str.len;
52                     blanks[nblanks].type = PKTLOG_BLANK;
53                     blanks[nblanks].len = str.len;
54                     nblanks++;
55                     /* If there's another password field beyond it
56                      * (change of password), blank that too. */
57                     str = get_string(src);
58                     if (!get_err(src))
59                         blanks[nblanks-1].len =
60                             src->pos - blanks[nblanks].offset;
61                 }
62             }
63         } else if (pls->actx == SSH2_PKTCTX_KBDINTER &&
64                    type == SSH2_MSG_USERAUTH_INFO_RESPONSE) {
65             /* If this is a keyboard-interactive response packet,
66              * blank the responses. */
67             get_uint32(src);
68             assert(nblanks < MAX_BLANKS);
69             blanks[nblanks].offset = src->pos;
70             blanks[nblanks].type = PKTLOG_BLANK;
71             do {
72                 str = get_string(src);
73             } while (!get_err(src));
74             blanks[nblanks].len = src->pos - blanks[nblanks].offset;
75             nblanks++;
76         } else if (type == SSH2_MSG_CHANNEL_REQUEST) {
77             /*
78              * If this is an X forwarding request packet, blank the
79              * fake auth data.
80              *
81              * Note that while we blank the X authentication data
82              * here, we don't take any special action to blank the
83              * start of an X11 channel, so using MIT-MAGIC-COOKIE-1
84              * and actually opening an X connection without having
85              * session blanking enabled is likely to leak your cookie
86              * into the log.
87              */
88             get_uint32(src);
89             str = get_string(src);
90             if (ptrlen_eq_string(str, "x11-req")) {
91                 get_bool(src);
92                 get_bool(src);
93                 get_string(src);
94                 str = get_string(src);
95                 if (!get_err(src)) {
96                     assert(nblanks < MAX_BLANKS);
97                     blanks[nblanks].offset = src->pos - str.len;
98                     blanks[nblanks].type = PKTLOG_BLANK;
99                     blanks[nblanks].len = str.len;
100                     nblanks++;
101                 }
102             }
103         }
104     }
105 
106     return nblanks;
107 }
108