aboutsummaryrefslogtreecommitdiffstats
path: root/fetchmail-SA-2007-02.txt
blob: 9fd5466c6aead8314088d7ad639368f149fa2dea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
fetchmail-SA-2007-02: Crash when a local warning message is rejected

Topics:		Crash when a fetchmail-generated warning message is rejected

Author:		Matthias Andree
Version:	1.1
Announced:	2007-08-28
Type:		NULL pointer dereference trigged by outside circumstances
Impact:		denial of service possible
Danger:		low
CVSS V2 vector: (AV:N/AC:M/Au:N/C:N/I:N/A:C/E:?/RL:O/RC:C)
		
Credits:	Earl Chew
CVE Name:	CVE-2007-4565
URL:		http://www.fetchmail.info/fetchmail-SA-2007-02.txt
Project URL:	http://www.fetchmail.info/

Affects:	fetchmail release < 6.3.9 exclusively

Not affected:	fetchmail release 6.3.9 and newer
		fetchmail releases < 4.6.8 exclusively

Corrected:	2007-07-29 fetchmail SVN (rev 5119)


0. Release history
==================

2007-07-29 1.0	first draft for MITRE/CVE (visible in SVN)
2007-08-28 1.1	reworked, added fix, official release


1. Background
=============

fetchmail is a software package to retrieve mail from remote POP2, POP3,
IMAP, ETRN or ODMR servers and forward it to local SMTP, LMTP servers or
message delivery agents.

fetchmail ships with a graphical, Python/Tkinter based configuration
utility named "fetchmailconf" to help the user create configuration (run
control) files for fetchmail.


2. Problem description and Impact
=================================

fetchmail will generate warning messages in certain circumstances and 
send them to the local postmaster or the user starting it. Such warning 
messages can be generated, for instance, if logging into an upstream 
server fails repeatedly or if messages beyond the size limit (if 
configured, default: no limit) are left on the server.

If this warning message is then refused by the SMTP listener that 
fetchmail is forwarding the message to, fetchmail attempts to 
dereference a NULL pointer when trying to find out if it should allow a 
bounce message to be sent.

This causes fetchmail to crash and not collect further messages until it 
is restarted.

Risk assessment: low. In default configuration, fetchmail will talk 
through the loopback interface, that means to the SMTP server on the same 
computer as it is running on. Otherwise, it will commonly be configured 
to talk to trusted SMTP servers, so a compromise or misconfiguration of 
a trusted or the same computer is required to exploit this problem - 
which usually opens up much easier ways of denying service, or worse.


3. Solution
===========

There are two alternatives, either of them by itself is sufficient:

a. Apply the patch found in section B of this announcement to fetchmail 6.3.8,
   recompile and reinstall it.

b. Install fetchmail 6.3.9 or newer when it becomes available.  The 
   fetchmail source code is available from 
   <http://developer.berlios.de/project/showfiles.php?group_id=1824>.

Note there are no workarounds presented here since all known workarounds 
are more intrusive than the actual solution.


A. Copyright, License and Warranty
==================================

(C) Copyright 2007 by Matthias Andree, <matthias.andree@gmx.de>.
Some rights reserved.

This work is licensed under the Creative Commons
Attribution-NonCommercial-NoDerivs German License. To view a copy of
this license, visit http://creativecommons.org/licenses/by-nc-nd/2.0/de/
or send a letter to Creative Commons; 559 Nathan Abbott Way;
Stanford, California 94305; USA.

THIS WORK IS PROVIDED FREE OF CHARGE AND WITHOUT ANY WARRANTIES.
Use the information herein at your own risk.



B. Patch to remedy the problem
==============================

Index: sink.c
===================================================================
--- sink.c	(revision 5118)
+++ sink.c	(revision 5119)
@@ -262,7 +262,7 @@
     const char *md1 = "MAILER-DAEMON", *md2 = "MAILER-DAEMON@";
 
     /* don't bounce in reply to undeliverable bounces */
-    if (!msg->return_path[0] ||
+    if (!msg || !msg->return_path[0] ||
 	strcmp(msg->return_path, "<>") == 0 ||
 	strcasecmp(msg->return_path, md1) == 0 ||
 	strncasecmp(msg->return_path, md2, strlen(md2)) == 0)

END OF fetchmail-SA-2007-02.txt
n>(buf[0] == '#') { pound_arg = atoi(buf+1); ok = 0; } else if (buf[0] == '=') { equal_arg = atoi(buf+1); ok = 0; } else if (buf[0] == '-') ok = PS_ERROR; else ok = PS_PROTOCOL; if (argbuf != NULL) strcpy(argbuf,buf); } return(ok); } int pop2_getauth(int sock, struct query *ctl, char *buf) /* apply for connection authorization */ { return(gen_transact(sock, "HELO %s %s", ctl->remotename, ctl->password)); } static int pop2_getrange(int sock, struct query *ctl, const char *folder, int*countp, int*newp) /* get range of messages to be fetched */ { /* maybe the user wanted a non-default folder */ if (folder) { int ok = gen_transact(sock, "FOLD %s", folder); if (ok != 0) return(ok); if (pound_arg == -1) return(PS_ERROR); } else /* * We should have picked up a count of messages in the user's * default inbox from the pop2_getauth() response. * * Note: this logic only works because there is no way to select * both the unnamed folder and named folders within a single * fetchmail run. If that assumption ever becomes invalid, the * pop2_getauth code will have to stash the pound response away * explicitly in case it gets stepped on. */ if (pound_arg == -1) return(PS_ERROR); *countp = pound_arg; *newp = -1; return(0); } static int pop2_fetch(int sock, struct query *ctl, int number, int *lenp) /* request nth message */ { int ok; *lenp = 0; ok = gen_transact(sock, "READ %d", number); if (ok) return(0); *lenp = equal_arg; gen_send(sock, "RETR"); return(ok); } static int pop2_trail(int sock, struct query *ctl, int number) /* send acknowledgement for message data */ { return(gen_transact(sock, ctl->keep ? "ACKS" : "ACKD")); } static int pop2_logout(int sock, struct query *ctl) /* send logout command */ { return(gen_transact(sock, "QUIT")); } const static struct method pop2 = { "POP2", /* Post Office Protocol v2 */ 109, /* standard POP2 port */ FALSE, /* this is not a tagged protocol */ FALSE, /* does not use message delimiter */ pop2_ok, /* parse command response */ pop2_getauth, /* get authorization */ pop2_getrange, /* query range of messages */ NULL, /* no way to get sizes */ NULL, /* messages are always new */ pop2_fetch, /* request given message */ NULL, /* no way to fetch body alone */ pop2_trail, /* eat message trailer */ NULL, /* no POP2 delete method */ pop2_logout, /* log out, we're done */ FALSE, /* no, we can't re-poll */ }; int doPOP2 (struct query *ctl) /* retrieve messages using POP2 */ { peek_capable = FALSE; return(do_protocol(ctl, &pop2)); } #endif /* POP2_ENABLE */ /* pop2.c ends here */