]> Pileus Git - ~andy/fetchmail/blob - contrib/rawlog.patch
fix another typo, point one URL to CVE.
[~andy/fetchmail] / contrib / rawlog.patch
1 This patch logs raw socket data, to assist debugging when discriminating
2 between server and fetchmail bugs.
3
4 Apply it to fetchmail 6.3.20 and set the environment variable
5 FETCHMAIL_RAW_LOGFILE to a log file writable by fetchmail. If it's not
6 there, it gets created with mode 0600 (which requires directory write
7 permission).
8
9 The file gets appended to, so you can log into named pipes, character
10 (stream) devices and to the console if you're so inclined.
11
12 Note 1: any logging failures cause fetchmail to abort() forcefully.
13
14 Note 2: non-printable characters are hex-escaped, so it is safe to use
15 FETCHMAIL_RAW_LOGFILE=/dev/stderr or similar.
16
17 -- Matthias Andree, August 2011
18
19 diff --git a/sink.c b/sink.c
20 index 5d92556..ff6208d 100644
21 --- a/sink.c
22 +++ b/sink.c
23 @@ -649,6 +649,10 @@ int stuffline(struct query *ctl, char *buf)
24      while ((last += strlen(last)) && (last[-1] != '\n'))
25          last++;
26  
27 +    if (outlevel >= O_DEBUG && (size_t)(last - buf) != strlen(buf))
28 +       report(stdout, GT_("DEBUG: stuffline shipping line with NULs, length=%lu, strlen=%lu\n"), last - buf, strlen(buf));
29 +
30 +
31      /* fix message lines that have only \n termination (for qmail) */
32      if (ctl->forcecr)
33      {
34 diff --git a/socket.c b/socket.c
35 index e338207..dcaf19d 100644
36 --- a/socket.c
37 +++ b/socket.c
38 @@ -381,6 +381,49 @@ static     SSL *_ssl_context[FD_SETSIZE];
39  static SSL     *SSLGetContext( int );
40  #endif /* SSL_ENABLE */
41  
42 +#include <fcntl.h>
43 +
44 +static const char *rawlogfile;
45 +static FILE *rlogstream;
46 +
47 +static int SockLog(void) {
48 +    static int haveinit;
49 +    static int wantlog;
50 +    static int logfd = -1;
51 +
52 +    if (!haveinit) {
53 +       haveinit = 1;
54 +       if ((rawlogfile = getenv("FETCHMAIL_RAW_LOGFILE"))) {
55 +           if ((logfd = open(rawlogfile, O_WRONLY|O_APPEND|O_CREAT, 0600)) == -1) {
56 +               report(stderr, GT_("FETCHMAIL_RAW_LOGFILE is set, but opening \"%s\" for appending write failed: %s\n"), rawlogfile, strerror(errno));
57 +               abort();
58 +           }
59 +           if (!(rlogstream = fdopen(logfd, "a"))) {
60 +               report(stderr, GT_("FETCHMAIL_RAW_LOGFILE is set, but fdopen(%d) failed: %s\n"), logfd, strerror(errno));
61 +               abort();
62 +           }
63 +           setvbuf(rlogstream, NULL, _IOLBF, 0);
64 +           wantlog = 1;
65 +       }
66 +    }
67 +    return wantlog;
68 +}
69 +
70 +static void LogPrintf(const char *fmt, ...) {
71 +    va_list va;
72 +    const char *locsav;
73 +    va_start(va, fmt);
74 +    if (!SockLog()) return;
75 +    locsav = setlocale(LC_ALL, NULL);
76 +    (void)setlocale(LC_ALL, "C");
77 +    if (EOF == vfprintf(rlogstream, fmt, va) || EOF == fflush(rlogstream)) {
78 +       report(stderr, GT_("FETCHMAIL_RAW_LOGFILE is set, but logging failed: %s\n"), strerror(errno));
79 +       abort();
80 +    }
81 +    (void)setlocale(LC_ALL, locsav);
82 +    va_end(va);
83 +}
84 +
85  int SockWrite(int sock, const char *buf, int len)
86  {
87      int n, wrlen = 0;
88 @@ -388,6 +431,12 @@ int SockWrite(int sock, const char *buf, int len)
89      SSL *ssl;
90  #endif
91  
92 +    if (SockLog()) {
93 +       char *tmps = sdump(buf, len);
94 +       LogPrintf("[>%d-%s count=%04d] %s\n", sock, SSLGetContext(sock) ? "crypt" : "plain", len, tmps);
95 +       free(tmps);
96 +    }
97 +
98      while (len)
99      {
100  #ifdef SSL_ENABLE
101 @@ -504,6 +553,13 @@ int SockRead(int sock, char *buf, int len)
102             (!newline && len);
103      *bp = '\0';
104  
105 +    if (SockLog())
106 +    {
107 +       char *tmps = sdump(buf, bp - buf);
108 +       LogPrintf("[<%d-%s count=%04d] %s\n", sock, SSLGetContext(sock) ? "crypt" : "plain", bp - buf, tmps);
109 +       free(tmps);
110 +    }
111 +
112      return bp - buf;
113  }
114