[Pkg-mailman-hackers] Pkg-mailman commit - rev 382 - in trunk/debian: . patches

Hector Garcia hector at costa.debian.org
Tue Sep 19 21:16:07 UTC 2006


Author: hector
Date: 2006-09-19 21:16:07 +0000 (Tue, 19 Sep 2006)
New Revision: 382

Added:
   trunk/debian/patches/23_CVE-2006-3636.dpatch
   trunk/debian/patches/24_CVE-2006-2941.dpatch
   trunk/debian/patches/25_CVE-2006-4624.dpatch
Modified:
   trunk/debian/changelog
   trunk/debian/patches/series
Log:
Added security patches from Lionel's port to sarge

Modified: trunk/debian/changelog
===================================================================
--- trunk/debian/changelog	2006-09-19 20:50:43 UTC (rev 381)
+++ trunk/debian/changelog	2006-09-19 21:16:07 UTC (rev 382)
@@ -37,8 +37,13 @@
   * Updated sv.po. Translated by Daniel Nylander. (Closes: #388090)
   * Updated hu.po. Translated by Laszlo Boszormenyi.
 
- -- Thijs Kinkhorst <thijs at debian.org>  Tue, 19 Sep 2006 13:52:06 +0200
+  [ Hector Garcia ]
+  * Added 24_CVE-2006-2941 taken from Lionel's port to sarge
+  * Added 23_CVE-2006-3636 taken from Lionel's port to sarge
+  * Added 25_CVE-2006-4624 taken from Lionel's port to sarge
 
+ -- Hector Garcia <hector at debian.org>  Tue, 19 Sep 2006 23:11:32 +0200
+
 mailman (1:2.1.8-2) unstable; urgency=low
 
   [ Thijs Kinkhorst ]

Added: trunk/debian/patches/23_CVE-2006-3636.dpatch
===================================================================
--- trunk/debian/patches/23_CVE-2006-3636.dpatch	                        (rev 0)
+++ trunk/debian/patches/23_CVE-2006-3636.dpatch	2006-09-19 21:16:07 UTC (rev 382)
@@ -0,0 +1,249 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 72_CVE-2006-3636.dpatch by  <lionel at mamane.lu>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: CVE-2006-3636.  Fixes for various cross-site scripting issues.
+## DP: Discovery by Moritz Naumann and most of the repair work done by
+## DP: Mark Sapiro (with some additional work by Barry).
+
+
+ at DPATCH@
+Index: Mailman/Cgi/admin.py
+===================================================================
+--- Mailman/Cgi/admin.py.orig	2005-12-30 19:50:07.000000000 +0100
++++ Mailman/Cgi/admin.py	2006-09-19 22:57:38.000000000 +0200
+@@ -1318,6 +1318,7 @@
+         # we display.  Try uploading a file with 10k names -- it takes a while
+         # to render the status page.
+         for entry in entries:
++            safeentry = Utils.websafe(entry)
+             fullname, address = parseaddr(entry)
+             # Canonicalize the full name
+             fullname = Utils.canonstr(fullname, mlist.preferred_language)
+@@ -1335,20 +1336,20 @@
+                                             send_admin_notif, invitation,
+                                             whence='admin mass sub')
+             except Errors.MMAlreadyAMember:
+-                subscribe_errors.append((entry, _('Already a member')))
++                subscribe_errors.append((safeentry, _('Already a member')))
+             except Errors.MMBadEmailError:
+                 if userdesc.address == '':
+                     subscribe_errors.append((_('&lt;blank line&gt;'),
+                                              _('Bad/Invalid email address')))
+                 else:
+-                    subscribe_errors.append((entry,
++                    subscribe_errors.append((safeentry,
+                                              _('Bad/Invalid email address')))
+             except Errors.MMHostileAddress:
+                 subscribe_errors.append(
+-                    (entry, _('Hostile address (illegal characters)')))
++                    (safeentry, _('Hostile address (illegal characters)')))
+             except Errors.MembershipIsBanned, pattern:
+                 subscribe_errors.append(
+-                    (entry, _('Banned address (matched %(pattern)s)')))
++                    (safeentry, _('Banned address (matched %(pattern)s)')))
+             else:
+                 member = Utils.uncanonstr(formataddr((fullname, address)))
+                 subscribe_success.append(Utils.websafe(member))
+@@ -1388,9 +1389,9 @@
+                     addr, whence='admin mass unsub',
+                     admin_notif=send_unsub_notifications,
+                     userack=userack)
+-                unsubscribe_success.append(addr)
++                unsubscribe_success.append(Utils.websafe(addr))
+             except Errors.NotAMemberError:
+-                unsubscribe_errors.append(addr)
++                unsubscribe_errors.append(Utils.websafe(addr))
+         if unsubscribe_success:
+             doc.AddItem(Header(5, _('Successfully Unsubscribed:')))
+             doc.AddItem(UnorderedList(*unsubscribe_success))
+Index: Mailman/Cgi/admindb.py
+===================================================================
+--- Mailman/Cgi/admindb.py.orig	2005-12-30 19:50:07.000000000 +0100
++++ Mailman/Cgi/admindb.py	2006-09-19 22:48:50.000000000 +0200
+@@ -313,7 +313,7 @@
+                      '&nbsp;' + _('Permanently ban from this list')
+         # While the address may be a unicode, it must be ascii
+         paddr = addr.encode('us-ascii', 'replace')
+-        table.AddRow(['%s<br><em>%s</em>' % (paddr, fullname),
++        table.AddRow(['%s<br><em>%s</em>' % (paddr, Utils.websafe(fullname)),
+                       radio,
+                       TextBox('comment-%d' % id, size=40)
+                       ])
+@@ -357,7 +357,7 @@
+             mlist.HandleRequest(id, mm_cfg.DISCARD)
+             continue
+         num += 1
+-        table.AddRow(['%s<br><em>%s</em>' % (addr, fullname),
++        table.AddRow(['%s<br><em>%s</em>' % (addr, Utils.websafe(fullname)),
+                       RadioButtonArray(id, (_('Defer'),
+                                             _('Approve'),
+                                             _('Reject'),
+Index: Mailman/Cgi/create.py
+===================================================================
+--- Mailman/Cgi/create.py.orig	2005-12-30 19:50:07.000000000 +0100
++++ Mailman/Cgi/create.py	2006-09-19 22:48:50.000000000 +0200
+@@ -190,15 +190,24 @@
+                 mlist.Create(listname, owner, pw, langs, emailhost)
+             finally:
+                 os.umask(oldmask)
+-        except Errors.EmailAddressError, s:
++        except Errors.EmailAddressError, e:
++            if e.args:
++                s = Utils.websafe(e.args[0])
++            else:
++                s = Utils.websafe(owner)
+             request_creation(doc, cgidata,
+                              _('Bad owner email address: %(s)s'))
+             return
+         except Errors.MMListAlreadyExistsError:
++            # MAS: List already exists so we don't need to websafe it.
+             request_creation(doc, cgidata,
+                              _('List already exists: %(listname)s'))
+             return
+-        except Errors.BadListNameError, s:
++        except Errors.BadListNameError, e:
++            if e.args:
++                s = Utils.websafe(e.args[0])
++            else:
++                s = Utils.websafe(listname)
+             request_creation(doc, cgidata,
+                              _('Illegal list name: %(s)s'))
+             return
+@@ -321,15 +330,17 @@
+     ftable.AddRow([Center(Italic(_('List Identity')))])
+     ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, colspan=2)
+ 
+-    safelistname = Utils.websafe(cgidata.getvalue('listname', ''))
++    listname = cgidata.getvalue('listname', '')
++    # MAS: Don't websafe twice.  TextBox does it.
+     ftable.AddRow([Label(_('Name of list:')),
+-                   TextBox('listname', safelistname)])
++                   TextBox('listname', listname)])
+     ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY)
+     ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY)
+ 
+-    safeowner = Utils.websafe(cgidata.getvalue('owner', ''))
++    owner = cgidata.getvalue('owner', '')
++    # MAS: Don't websafe twice.  TextBox does it.
+     ftable.AddRow([Label(_('Initial list owner address:')),
+-                   TextBox('owner', safeowner)])
++                   TextBox('owner', owner)])
+     ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 0, bgcolor=GREY)
+     ftable.AddCellInfo(ftable.GetCurrentRowIndex(), 1, bgcolor=GREY)
+ 
+Index: Mailman/Cgi/edithtml.py
+===================================================================
+--- Mailman/Cgi/edithtml.py.orig	2006-01-09 08:06:52.000000000 +0100
++++ Mailman/Cgi/edithtml.py	2006-09-19 22:48:50.000000000 +0200
+@@ -143,7 +143,8 @@
+     doc.AddItem('<p>')
+     doc.AddItem('<hr>')
+     form = Form(mlist.GetScriptURL('edithtml') + '/' + template_name)
+-    text = Utils.websafe(Utils.maketext(template_name, raw=1, mlist=mlist))
++    text = Utils.maketext(template_name, raw=1, mlist=mlist)
++    # MAS: Don't websafe twice.  TextArea does it.
+     form.AddItem(TextArea('html_code', text, rows=40, cols=75))
+     form.AddItem('<p>' + _('When you are done making changes...'))
+     form.AddItem(SubmitButton('submit', _('Submit Changes')))
+Index: Mailman/Cgi/options.py
+===================================================================
+--- Mailman/Cgi/options.py.orig	2005-12-03 02:07:13.000000000 +0100
++++ Mailman/Cgi/options.py	2006-09-19 22:48:50.000000000 +0200
+@@ -702,7 +702,7 @@
+ 
+     fullname = Utils.uncanonstr(mlist.getMemberName(user), userlang)
+     if fullname:
+-        presentable_user += ', %s' % fullname
++        presentable_user += ', %s' % Utils.websafe(fullname)
+ 
+     # Do replacements
+     replacements = mlist.GetStandardReplacements(userlang)
+Index: Mailman/Gui/General.py
+===================================================================
+--- Mailman/Gui/General.py.orig	2006-03-23 11:51:25.000000000 +0100
++++ Mailman/Gui/General.py	2006-09-19 22:48:50.000000000 +0200
+@@ -439,13 +439,13 @@
+             GUIBase._setValue(self, mlist, property, val, doc)
+ 
+     def _escape(self, property, value):
+-        # The 'info' property allows HTML, but lets sanitize it to avoid XSS
++        # The 'info' property allows HTML, but let's sanitize it to avoid XSS
+         # exploits.  Everything else should be fully escaped.
+         if property <> 'info':
+             return GUIBase._escape(self, property, value)
+         # Sanitize <script> and </script> tags but nothing else.  Not the best
+         # solution, but expedient.
+-        return re.sub(r'<([/]?script.*?)>', r'&lt;\1&gt;', value)
++        return re.sub(r'(?i)<([/]?script.*?)>', r'&lt;\1&gt;', value)
+ 
+     def _postValidate(self, mlist, doc):
+         if not mlist.reply_to_address.strip() and \
+Index: Mailman/HTMLFormatter.py
+===================================================================
+--- Mailman/HTMLFormatter.py.orig	2005-08-27 03:40:15.000000000 +0200
++++ Mailman/HTMLFormatter.py	2006-09-19 22:48:50.000000000 +0200
+@@ -1,4 +1,4 @@
+-# Copyright (C) 1998-2003 by the Free Software Foundation, Inc.
++# Copyright (C) 1998-2006 by the Free Software Foundation, Inc.
+ #
+ # This program is free software; you can redistribute it and/or
+ # modify it under the terms of the GNU General Public License
+@@ -332,8 +332,12 @@
+         return '</FORM>'
+ 
+     def FormatBox(self, name, size=20, value=''):
++        if isinstance(value, str):
++            safevalue = Utils.websafe(value)
++        else:
++            safevalue = value
+         return '<INPUT type="Text" name="%s" size="%d" value="%s">' % (
+-            name, size, value)
++            name, size, safevalue)
+ 
+     def FormatSecureBox(self, name):
+         return '<INPUT type="Password" name="%s" size="15">' % name
+Index: Mailman/Utils.py
+===================================================================
+--- Mailman/Utils.py.orig	2006-03-18 18:23:04.000000000 +0100
++++ Mailman/Utils.py	2006-09-19 22:48:50.000000000 +0200
+@@ -204,7 +204,7 @@
+ _badchars = re.compile(r'[][()<>|;^,\000-\037\177-\377]')
+ 
+ def ValidateEmail(s):
+-    """Verify that the an email address isn't grossly evil."""
++    """Verify that an email address isn't grossly evil."""
+     # Pretty minimal, cheesy check.  We could do better...
+     if not s or s.count(' ') > 0:
+         raise Errors.MMBadEmailError
+Index: Mailman/htmlformat.py
+===================================================================
+--- Mailman/htmlformat.py.orig	2005-08-27 03:40:15.000000000 +0200
++++ Mailman/htmlformat.py	2006-09-19 22:48:50.000000000 +0200
+@@ -448,7 +448,11 @@
+ 
+ class TextBox(InputObj):
+     def __init__(self, name, value='', size=mm_cfg.TEXTFIELDWIDTH):
+-        InputObj.__init__(self, name, "TEXT", value, checked=0, size=size)
++        if isinstance(value, str):
++            safevalue = Utils.websafe(value)
++        else:
++            safevalue = value
++        InputObj.__init__(self, name, "TEXT", safevalue, checked=0, size=size)
+ 
+ class Hidden(InputObj):
+     def __init__(self, name, value=''):
+@@ -457,8 +461,12 @@
+ class TextArea:
+     def __init__(self, name, text='', rows=None, cols=None, wrap='soft',
+                  readonly=0):
++        if isinstance(text, str):
++            safetext = Utils.websafe(text)
++        else:
++            safetext = text
+         self.name = name
+-        self.text = text
++        self.text = safetext
+         self.rows = rows
+         self.cols = cols
+         self.wrap = wrap

Added: trunk/debian/patches/24_CVE-2006-2941.dpatch
===================================================================
--- trunk/debian/patches/24_CVE-2006-2941.dpatch	                        (rev 0)
+++ trunk/debian/patches/24_CVE-2006-2941.dpatch	2006-09-19 21:16:07 UTC (rev 382)
@@ -0,0 +1,441 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 73_CVE-2006-2941.dpatch by  <lionel at mamane.lu>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: CVE-2006-2941: DoS caused by standards-breaking RFC 2231 formatted headers.
+
+ at DPATCH@
+Index: misc/CVE-2006-2941.patch
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ misc/CVE-2006-2941.patch	2006-09-19 23:02:23.000000000 +0200
+@@ -0,0 +1,414 @@
++diff --recursive -u email-2.5.7/email/__init__.py email-2.5.8/email/__init__.py
++--- email-2.5.7/email/__init__.py	2006-03-06 01:23:54.000000000 +0100
+++++ email-2.5.8/email/__init__.py	2006-07-25 15:10:39.000000000 +0200
++@@ -3,7 +3,7 @@
++
++ """A package for parsing, handling, and generating email messages."""
++
++-__version__ = '2.5.5'
+++__version__ = '2.5.5.debian1'
++
++ __all__ = [
++     'base64MIME',
++diff --recursive -u email-2.5.7/email/_parseaddr.py email-2.5.8/email/_parseaddr.py
++--- email-2.5.7/email/_parseaddr.py	2006-03-06 01:23:54.000000000 +0100
+++++ email-2.5.8/email/_parseaddr.py	2006-06-13 05:43:49.000000000 +0200
++@@ -365,6 +365,7 @@
++                 break
++             elif allowcomments and self.field[self.pos] == '(':
++                 slist.append(self.getcomment())
+++                continue        # have already advanced pos from getcomment
++             elif self.field[self.pos] == '\\':
++                 quote = True
++             else:
++diff --recursive -u email-2.5.7/email/test/test_email.py email-2.5.8/email/test/test_email.py
++--- email-2.5.7/email/test/test_email.py	2006-03-06 01:23:53.000000000 +0100
+++++ email-2.5.8/email/test/test_email.py	2006-07-26 05:58:13.000000000 +0200
++@@ -9,7 +9,7 @@
++ import unittest
++ import warnings
++ from cStringIO import StringIO
++-from types import StringType, ListType
+++from types import StringType, ListType, TupleType
++
++ import email
++
++@@ -2064,6 +2064,12 @@
++            ['foo: ;', '"Jason R. Mastaler" <jason at dom.ain>']),
++            [('', ''), ('Jason R. Mastaler', 'jason at dom.ain')])
++
+++    def test_getaddresses_embedded_comment(self):
+++        """Test proper handling of a nested comment"""
+++        eq = self.assertEqual
+++        addrs = Utils.getaddresses(['User ((nested comment)) <foo at bar.com>'])
+++        eq(addrs[0][1], 'foo at bar.com')
+++
++     def test_utils_quote_unquote(self):
++         eq = self.assertEqual
++         msg = Message()
++@@ -2750,14 +2756,17 @@
++
++ '''
++         msg = email.message_from_string(m)
++-        self.assertEqual(msg.get_param('NAME'),
++-                         (None, None, 'file____C__DOCUMENTS_20AND_20SETTINGS_FABIEN_LOCAL_20SETTINGS_TEMP_nsmail.htm'))
+++        param = msg.get_param('NAME')
+++        self.failIf(isinstance(param, TupleType))
+++        self.assertEqual(
+++            param,
+++            'file____C__DOCUMENTS_20AND_20SETTINGS_FABIEN_LOCAL_20SETTINGS_TEMP_nsmail.htm')
++
++     def test_rfc2231_no_language_or_charset_in_filename(self):
++         m = '''\
++ Content-Disposition: inline;
++-\tfilename*0="This%20is%20even%20more%20";
++-\tfilename*1="%2A%2A%2Afun%2A%2A%2A%20";
+++\tfilename*0*="This%20is%20even%20more%20";
+++\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20";
++ \tfilename*2="is it not.pdf"
++
++ '''
++@@ -2768,8 +2777,8 @@
++     def test_rfc2231_no_language_or_charset_in_boundary(self):
++         m = '''\
++ Content-Type: multipart/alternative;
++-\tboundary*0="This%20is%20even%20more%20";
++-\tboundary*1="%2A%2A%2Afun%2A%2A%2A%20";
+++\tboundary*0*="This%20is%20even%20more%20";
+++\tboundary*1*="%2A%2A%2Afun%2A%2A%2A%20";
++ \tboundary*2="is it not.pdf"
++
++ '''
++@@ -2777,12 +2786,38 @@
++         self.assertEqual(msg.get_boundary(),
++                          'This is even more ***fun*** is it not.pdf')
++
+++    def test_rfc2231_partly_encoded(self):
+++        m = '''\
+++Content-Disposition: inline;
+++\tfilename*0="''This%20is%20even%20more%20";
+++\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20";
+++\tfilename*2="is it not.pdf"
+++
+++'''
+++        msg = email.message_from_string(m)
+++        self.assertEqual(
+++            msg.get_filename(),
+++            'This%20is%20even%20more%20***fun*** is it not.pdf')
+++
+++    def test_rfc2231_partly_nonencoded(self):
+++        m = '''\
+++Content-Disposition: inline;
+++\tfilename*0="This%20is%20even%20more%20";
+++\tfilename*1="%2A%2A%2Afun%2A%2A%2A%20";
+++\tfilename*2="is it not.pdf"
+++
+++'''
+++        msg = email.message_from_string(m)
+++        self.assertEqual(
+++            msg.get_filename(),
+++            'This%20is%20even%20more%20%2A%2A%2Afun%2A%2A%2A%20is it not.pdf')
+++
++     def test_rfc2231_no_language_or_charset_in_charset(self):
++         # This is a nonsensical charset value, but tests the code anyway
++         m = '''\
++ Content-Type: text/plain;
++-\tcharset*0="This%20is%20even%20more%20";
++-\tcharset*1="%2A%2A%2Afun%2A%2A%2A%20";
+++\tcharset*0*="This%20is%20even%20more%20";
+++\tcharset*1*="%2A%2A%2Afun%2A%2A%2A%20";
++ \tcharset*2="is it not.pdf"
++
++ '''
++@@ -2793,8 +2828,8 @@
++     def test_rfc2231_bad_encoding_in_filename(self):
++         m = '''\
++ Content-Disposition: inline;
++-\tfilename*0="bogus'xx'This%20is%20even%20more%20";
++-\tfilename*1="%2A%2A%2Afun%2A%2A%2A%20";
+++\tfilename*0*="bogus'xx'This%20is%20even%20more%20";
+++\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20";
++ \tfilename*2="is it not.pdf"
++
++ '''
++@@ -2825,9 +2860,9 @@
++     def test_rfc2231_bad_character_in_filename(self):
++         m = '''\
++ Content-Disposition: inline;
++-\tfilename*0="ascii'xx'This%20is%20even%20more%20";
++-\tfilename*1="%2A%2A%2Afun%2A%2A%2A%20";
++-\tfilename*2="is it not.pdf%E2"
+++\tfilename*0*="ascii'xx'This%20is%20even%20more%20";
+++\tfilename*1*="%2A%2A%2Afun%2A%2A%2A%20";
+++\tfilename*2*="is it not.pdf%E2"
++
++ '''
++         msg = email.message_from_string(m)
++@@ -2835,6 +2870,102 @@
++                          'This is even more ***fun*** is it not.pdf\xe2')
++
++
+++    def test_rfc2231_unknown_encoding(self):
+++        m = """\
+++Content-Transfer-Encoding: 8bit
+++Content-Disposition: inline; filename*=X-UNKNOWN''myfile.txt
+++
+++"""
+++        msg = email.message_from_string(m)
+++        self.assertEqual(msg.get_filename(), 'myfile.txt')
+++
+++    def test_rfc2231_single_tick_in_filename_extended(self):
+++        eq = self.assertEqual
+++        m = """\
+++Content-Type: application/x-foo;
+++\tname*0*=\"Frank's\"; name*1*=\" Document\"
+++
+++"""
+++        msg = email.message_from_string(m)
+++        charset, language, s = msg.get_param('name')
+++        eq(charset, None)
+++        eq(language, None)
+++        eq(s, "Frank's Document")
+++
+++    def test_rfc2231_single_tick_in_filename(self):
+++        m = """\
+++Content-Type: application/x-foo; name*0=\"Frank's\"; name*1=\" Document\"
+++
+++"""
+++        msg = email.message_from_string(m)
+++        param = msg.get_param('name')
+++        self.failIf(isinstance(param, TupleType))
+++        self.assertEqual(param, "Frank's Document")
+++
+++    def test_rfc2231_tick_attack_extended(self):
+++        eq = self.assertEqual
+++        m = """\
+++Content-Type: application/x-foo;
+++\tname*0*=\"us-ascii'en-us'Frank's\"; name*1*=\" Document\"
+++
+++"""
+++        msg = email.message_from_string(m)
+++        charset, language, s = msg.get_param('name')
+++        eq(charset, 'us-ascii')
+++        eq(language, 'en-us')
+++        eq(s, "Frank's Document")
+++
+++    def test_rfc2231_tick_attack(self):
+++        m = """\
+++Content-Type: application/x-foo;
+++\tname*0=\"us-ascii'en-us'Frank's\"; name*1=\" Document\"
+++
+++"""
+++        msg = email.message_from_string(m)
+++        param = msg.get_param('name')
+++        self.failIf(isinstance(param, TupleType))
+++        self.assertEqual(param, "us-ascii'en-us'Frank's Document")
+++
+++    def test_rfc2231_no_extended_values(self):
+++        eq = self.assertEqual
+++        m = """\
+++Content-Type: application/x-foo; name=\"Frank's Document\"
+++
+++"""
+++        msg = email.message_from_string(m)
+++        eq(msg.get_param('name'), "Frank's Document")
+++
+++    def test_rfc2231_encoded_then_unencoded_segments(self):
+++        eq = self.assertEqual
+++        m = """\
+++Content-Type: application/x-foo;
+++\tname*0*=\"us-ascii'en-us'My\";
+++\tname*1=\" Document\";
+++\tname*2*=\" For You\"
+++
+++"""
+++        msg = email.message_from_string(m)
+++        charset, language, s = msg.get_param('name')
+++        eq(charset, 'us-ascii')
+++        eq(language, 'en-us')
+++        eq(s, 'My Document For You')
+++
+++    def test_rfc2231_unencoded_then_encoded_segments(self):
+++        eq = self.assertEqual
+++        m = """\
+++Content-Type: application/x-foo;
+++\tname*0=\"us-ascii'en-us'My\";
+++\tname*1*=\" Document\";
+++\tname*2*=\" For You\"
+++
+++"""
+++        msg = email.message_from_string(m)
+++        charset, language, s = msg.get_param('name')
+++        eq(charset, 'us-ascii')
+++        eq(language, 'en-us')
+++        eq(s, 'My Document For You')
+++
+++
++ 
++ def _testclasses():
++     mod = sys.modules[__name__]
++diff --recursive -u email-2.5.7/email/Utils.py email-2.5.8/email/Utils.py
++--- email-2.5.7/email/Utils.py	2006-03-06 01:23:54.000000000 +0100
+++++ email-2.5.8/email/Utils.py	2006-07-25 15:10:39.000000000 +0200
++@@ -1,14 +1,15 @@
++-# Copyright (C) 2001,2002 Python Software Foundation
++-# Author: barry at zope.com (Barry Warsaw)
+++# Copyright (C) 2001-2006 Python Software Foundation
+++# Author: Barry Warsaw
+++# Contact: email-sig at python.org
++
++-"""Miscellaneous utilities.
++-"""
+++"""Miscellaneous utilities."""
++
++ import time
++ import socket
++ import re
++ import random
++ import os
+++import urllib
++ import warnings
++ from cStringIO import StringIO
++ from types import ListType
++@@ -53,6 +54,7 @@
++ EMPTYSTRING = ''
++ UEMPTYSTRING = u''
++ CRLF = '\r\n'
+++TICK = "'"
++
++ specialsre = re.compile(r'[][\\()<>@,:;".]')
++ escapesre = re.compile(r'[][\\()"]')
++@@ -277,12 +279,14 @@
++ # RFC2231-related functions - parameter encoding and decoding
++ def decode_rfc2231(s):
++     """Decode string according to RFC 2231"""
++-    import urllib
++-    parts = s.split("'", 2)
++-    if len(parts) == 1:
+++    parts = s.split(TICK, 2)
+++    if len(parts) <= 2:
++         return None, None, urllib.unquote(s)
++-    charset, language, s = parts
++-    return charset, language, urllib.unquote(s)
+++    if len(parts) > 3:
+++        charset, language = pars[:2]
+++        s = TICK.join(parts[2:])
+++        return charset, language, s
+++    return parts
++
++
++ def encode_rfc2231(s, charset=None, language=None):
++@@ -306,35 +310,52 @@
++ def decode_params(params):
++     """Decode parameters list according to RFC 2231.
++
++-    params is a sequence of 2-tuples containing (content type, string value).
+++    params is a sequence of 2-tuples containing (param name, string value).
++     """
+++    # Copy params so we don't mess with the original
+++    params = params[:]
++     new_params = []
++-    # maps parameter's name to a list of continuations
+++    # Map parameter's name to a list of continuations.  The values are a
+++    # 3-tuple of the continuation number, the string value, and a flag
+++    # specifying whether a particular segment is %-encoded.
++     rfc2231_params = {}
++-    # params is a sequence of 2-tuples containing (content_type, string value)
++-    name, value = params[0]
+++    name, value = params.pop(0)
++     new_params.append((name, value))
++-    # Cycle through each of the rest of the parameters.
++-    for name, value in params[1:]:
+++    while params:
+++        name, value = params.pop(0)
+++        if name.endswith('*'):
+++            encoded = True
+++        else:
+++            encoded = False
++         value = unquote(value)
++         mo = rfc2231_continuation.match(name)
++         if mo:
++             name, num = mo.group('name', 'num')
++             if num is not None:
++                 num = int(num)
++-            rfc2231_param1 = rfc2231_params.setdefault(name, [])
++-            rfc2231_param1.append((num, value))
+++            rfc2231_params.setdefault(name, []).append((num, value, encoded))
++         else:
++             new_params.append((name, '"%s"' % quote(value)))
++     if rfc2231_params:
++         for name, continuations in rfc2231_params.items():
++             value = []
+++            extended = False
++             # Sort by number
++             continuations.sort()
++-            # And now append all values in num order
++-            for num, continuation in continuations:
++-                value.append(continuation)
++-            charset, language, value = decode_rfc2231(EMPTYSTRING.join(value))
++-            new_params.append(
++-                (name, (charset, language, '"%s"' % quote(value))))
+++            # And now append all values in numerical order, converting
+++            # %-encodings for the encoded segments.  If any of the
+++            # continuation names ends in a *, then the entire string, after
+++            # decoding segments and concatenating, must have the charset and
+++            # language specifiers at the beginning of the string.
+++            for num, s, encoded in continuations:
+++                if encoded:
+++                    s = urllib.unquote(s)
+++                    extended = True
+++                value.append(s)
+++            value = quote(EMPTYSTRING.join(value))
+++            if extended:
+++                charset, language, value = decode_rfc2231(value)
+++                new_params.append((name, (charset, language, '"%s"' % value)))
+++            else:
+++                new_params.append((name, '"%s"' % value))
++     return new_params
++diff --recursive -u email-2.5.7/PKG-INFO email-2.5.8/PKG-INFO
++--- email-2.5.7/PKG-INFO	2006-03-06 02:39:57.000000000 +0100
+++++ email-2.5.8/PKG-INFO	2006-07-26 06:15:58.000000000 +0200
++@@ -1,10 +1,10 @@
++ Metadata-Version: 1.0
++ Name: email
++-Version: 2.5.5
+++Version: 2.5.5.debian1
++ Summary: Standalone email package
++ Home-page: http://www.python.org/sigs/email-sig
++ Author: Barry Warsaw
++-Author-email: barry at python.org
+++Author-email: email-sig at python.org
++ License: UNKNOWN
++ Description: UNKNOWN
++ Platform: UNKNOWN
++diff --recursive -u email-2.5.7/setup.py email-2.5.8/setup.py
++--- email-2.5.7/setup.py	2006-03-06 01:21:59.000000000 +0100
+++++ email-2.5.8/setup.py	2006-07-25 16:08:43.000000000 +0200
++@@ -1,5 +1,3 @@
++-#! /usr/bin/env python
++-#
++ # Copyright (C) 2001-2006 Python Software Foundation
++
++ # Standard distutils setup.py install script for the `mimelib' library, a next
++@@ -20,7 +18,7 @@
++       version=email.__version__,
++       description='Standalone email package',
++       author='Barry Warsaw',
++-      author_email='barry at python.org',
+++      author_email='email-sig at python.org',
++       url='http://www.python.org/sigs/email-sig',
++       packages=['email'],
++       )
++diff --recursive -u email-2.5.7/testall.py email-2.5.8/testall.py
++--- email-2.5.7/testall.py	2006-03-06 01:21:59.000000000 +0100
+++++ email-2.5.8/testall.py	2006-07-25 16:09:00.000000000 +0200
++@@ -13,8 +13,8 @@
++ """
++
++ import sys
++-import unittest
++ import getopt
+++import unittest
++
++ from email.test import test_email
++
+Index: misc/Makefile.in
+===================================================================
+--- misc/Makefile.in.orig	2006-09-19 23:01:05.000000000 +0200
++++ misc/Makefile.in	2006-09-19 23:01:08.000000000 +0200
+@@ -94,7 +94,9 @@
+ 	for p in $(PACKAGES); \
+ 	do \
+ 	    gunzip -c $(srcdir)/$$p.tar.gz | (cd $(PKGDIR) ; tar xf -); \
+-	    (cd $(PKGDIR)/$$p ; umask 02 ; PYTHONPATH=$(PYTHONLIBDIR) $(PYTHON) $(SETUPCMD)); \
++	    (cd $(PKGDIR)/$$p ; umask 02 ; \
++	     if [ "$$p" = "email-2.5.5" ]; then patch -p1 "$(PWD)/CVE-2006-2941.patch"; fi; \
++	     PYTHONPATH=$(PYTHONLIBDIR) $(PYTHON) $(SETUPCMD)); \
+ 	done
+ 
+ finish:

Added: trunk/debian/patches/25_CVE-2006-4624.dpatch
===================================================================
--- trunk/debian/patches/25_CVE-2006-4624.dpatch	                        (rev 0)
+++ trunk/debian/patches/25_CVE-2006-4624.dpatch	2006-09-19 21:16:07 UTC (rev 382)
@@ -0,0 +1,44 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 74_CVE-2006-4624.dpatch by  <lionel at mamane.lu>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Security: log injection vulnerability
+
+ at DPATCH@
+Index: Mailman/Utils.py
+===================================================================
+--- Mailman/Utils.py.orig	2006-09-19 22:58:19.000000000 +0200
++++ Mailman/Utils.py	2006-09-19 23:03:24.000000000 +0200
+@@ -53,6 +53,7 @@
+ from Mailman import Errors
+ from Mailman import Site
+ from Mailman.SafeDict import SafeDict
++from Mailman.Logging.Syslog import syslog
+ 
+ try:
+     True, False
+@@ -219,9 +220,16 @@
+ 
+ 
+ 
++# Patterns which may be used to form malicious path to inject a new
++# line in the mailman error log. (TK: advisory by Moritz Naumann)
++CRNLpat = re.compile(r'[^\x21-\x7e]')
++
+ def GetPathPieces(envar='PATH_INFO'):
+     path = os.environ.get(envar)
+     if path:
++        if CRNLpat.search(path):
++            path = CRNLpat.split(path)[0]
++            syslog('error', 'Warning: Possible malformed path attack.')
+         return [p for p in path.split('/') if p]
+     return None
+ 
+@@ -541,7 +549,6 @@
+                 text = sdict.interpolate(utemplate)
+         except (TypeError, ValueError), e:
+             # The template is really screwed up
+-            from Mailman.Logging.Syslog import syslog
+             syslog('error', 'broken template: %s\n%s', filename, e)
+             pass
+     if raw:

Modified: trunk/debian/patches/series
===================================================================
--- trunk/debian/patches/series	2006-09-19 20:50:43 UTC (rev 381)
+++ trunk/debian/patches/series	2006-09-19 21:16:07 UTC (rev 382)
@@ -9,6 +9,9 @@
 16_update_debian.patch -p0
 20_qmail_to_mailman.debian.patch -p0
 21_newlist_help.patch -p0
+23_CVE-2006-3636.dpatch -p0
+24_CVE-2006-2941.dpatch -p0
+25_CVE-2006-4624.dpatch -p0
 30_pipermail_threads.patch -p0
 32_MIME_fixup.patch -p0
 51_nocompile.pyc.patch -p0




More information about the Pkg-mailman-hackers mailing list