Index: NEWS
===================================================================
RCS file: /cvsroot/mailman/mailman/NEWS,v
retrieving revision 1.25.2.6
retrieving revision 1.25.2.9
diff -u -r1.25.2.6 -r1.25.2.9
--- NEWS        2001/05/03 21:06:56     1.25.2.6
+++ NEWS        2001/07/25 18:52:27     1.25.2.9
@@ -4,6 +4,34 @@

Here is a history of user visible changes to Mailman.

+2.0.6 (25-Jul-2001)
+
+    Security fix:
+
+    - Fixed a potential security hole which could allow access to list
+      administrative features by unauthorized users.  If there is an
+      empty data/adm.pw file (the site password file), then any
+      password will be accepted as the list administrative password.
+      This exploit is caused by a common "bug" in the crypt() function
+      suffered by several Unix distributions, including at least
+      GNU/Linux and Solaris.  Given a salt string of length zero,
+      crypt() always returns the empty string.
+
+      In lieu of applying this patch, sites can run bin/mmsitepass and
+      ensure that data/adm.pw is of length 2 or greater.
+
+    Bug fixes:
+
+    - Ensure that even if DEFAULT_URL is misconfigured in mm_cfg.py
+      (i.e. is missing a trailing slash), it is always fixed upon list
+      creation.
+
+    - Check for administrivia holds before any other tests.
+
+    - SF bugs fixed: 407666, 227694
+
+    - Other miscellaneous buglets fixed.
+
2.0.5 (04-May-2001)

    Fix a lock stagnation problem that can result when the user hits
Index: Mailman/MailList.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/MailList.py,v
retrieving revision 1.189
retrieving revision 1.189.2.2
diff -u -r1.189 -r1.189.2.2
--- Mailman/MailList.py 2000/11/16 04:33:27     1.189
+++ Mailman/MailList.py 2001/05/29 14:45:27     1.189.2.2
@@ -1,4 +1,4 @@
-# Copyright (C) 1998,1999,2000 by the Free Software Foundation, Inc.
+# Copyright (C) 1998,1999,2000,2001 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
@@ -712,7 +712,7 @@
             " fails, or if the pattern does contain an `@', then the pattern"
             " is matched against the entire recipient address. "
             " <p>Matching against the local part is deprecated; in a future"
-             " release, the patterm will always be matched against the "
+             " release, the pattern will always be matched against the "
             " entire recipient address."),

           ('max_num_recipients', mm_cfg.Number, 5, 0,
@@ -787,6 +787,7 @@
        self.InitVars(name, admin, crypted_password)
        self._ready = 1
        self.InitTemplates()
+        self.CheckValues()
        self.Save()
       # Touch these files so they have the right dir perms no matter what.
       # A "just-in-case" thing.  This shouldn't have to be here.
Index: Mailman/SecurityManager.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/SecurityManager.py,v
retrieving revision 1.31
retrieving revision 1.31.2.1
diff -u -r1.31 -r1.31.2.1
--- Mailman/SecurityManager.py  2000/10/02 20:40:41     1.31
+++ Mailman/SecurityManager.py  2001/07/25 18:07:51     1.31.2.1
@@ -1,4 +1,4 @@
-# Copyright (C) 1998,1999,2000 by the Free Software Foundation, Inc.
+# Copyright (C) 1998,1999,2000,2001 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
@@ -44,8 +44,12 @@
    def ValidAdminPassword(self, pw):
       if Utils.CheckSiteAdminPassword(pw):
            return 1
-       return type(pw) == StringType and \
-               Crypt.crypt(pw, self.password) == self.password
+        salt = self.password[:2]
+        # crypt() has a bug in that if the salt is the empty string, it will
+        # always return the empty string, regardless of the key. :(
+        if len(salt) < 2:
+            return 0
+       return Crypt.crypt(pw, salt) == self.password

    def ConfirmAdminPassword(self, pw):
        if not self.ValidAdminPassword(pw):
Index: Mailman/Utils.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Utils.py,v
retrieving revision 1.104.2.2
retrieving revision 1.104.2.4
diff -u -r1.104.2.2 -r1.104.2.4
--- Mailman/Utils.py    2001/04/18 04:23:07     1.104.2.2
+++ Mailman/Utils.py    2001/07/25 18:06:46     1.104.2.4
@@ -262,7 +262,7 @@
           finally:
               os.umask(ou)
           if verbose:
-               print 'made directory: ', madepart
+               print 'made directory: ', made_part



@@ -405,7 +405,12 @@
        f = open(mm_cfg.SITE_PW_FILE)
        pw2 = f.read()
        f.close()
-        return Crypt.crypt(pw1, pw2[:2]) == pw2
+        salt = pw2[:2]
+        # crypt() has a bug in that if the salt is the empty string, it will
+        # always return the empty string, regardless of the key. :(
+        if len(salt) < 2:
+            return 0
+        return Crypt.crypt(pw1, salt) == pw2
    # There probably is no site admin password if there was an exception
    except IOError:
        return 0
Index: Mailman/Version.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Version.py,v
retrieving revision 1.20.2.5
retrieving revision 1.20.2.6
diff -u -r1.20.2.5 -r1.20.2.6
--- Mailman/Version.py  2001/05/03 20:58:19     1.20.2.5
+++ Mailman/Version.py  2001/07/25 18:05:30     1.20.2.6
@@ -15,7 +15,7 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

# Mailman version
-VERSION = "2.0.5"
+VERSION = "2.0.6"

# And as a hex number in the manner of PY_VERSION_HEX
ALPHA = 0xa
@@ -27,7 +27,7 @@

MAJOR_REV = 2
MINOR_REV = 0
-MICRO_REV = 5
+MICRO_REV = 6
REL_LEVEL = FINAL
# at most 15 beta releases!
REL_SERIAL = 0
Index: Mailman/versions.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/versions.py,v
retrieving revision 1.27
retrieving revision 1.27.2.1
diff -u -r1.27 -r1.27.2.1
--- Mailman/versions.py 2000/06/14 05:09:58     1.27
+++ Mailman/versions.py 2001/07/10 14:58:56     1.27.2.1
@@ -142,7 +142,7 @@
    # set admin_notify_mchanges
    #
    if not hasattr(l, "admin_notify_mchanges"):
-        setatrr(l, "admin_notify_mchanges",
+        setattr(l, "admin_notify_mchanges",
                mm_cfg.DEFAULT_ADMIN_NOTIFY_MCHANGES)
    #
    # Convert the members and digest_members addresses so that the keys of
Index: Mailman/Archiver/pipermail.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Archiver/pipermail.py,v
retrieving revision 1.15
retrieving revision 1.15.2.2
diff -u -r1.15 -r1.15.2.2
--- Mailman/Archiver/pipermail.py       2000/10/20 06:18:11     1.15
+++ Mailman/Archiver/pipermail.py       2001/06/01 22:30:16     1.15.2.2
@@ -62,7 +62,7 @@

# Abstract class for databases

-class DatabaseInterface:
+class DatabaseInterface:
    def __init__(self): pass
    def close(self): pass
    def getArticle(self, archive, msgid): pass
@@ -162,13 +162,15 @@
       id = strip_separators(message.getheader('Message-Id'))
       if id == "":
            self.msgid = str(self.sequence)
-       else: self.msgid = id
+       else:
+            self.msgid = id

       if message.has_key('Subject'):
            self.subject = str(message['Subject'])
       else:
+            self.subject = 'No subject'
+       if self.subject == "":
            self.subject = 'No subject'
-       if self.subject == "": self.subject = 'No subject'

        self._set_date(message)

@@ -180,7 +182,8 @@
       self.email = strip_separators(self.email)
       self.author = strip_separators(self.author)

-       if self.author == "": self.author = self.email
+       if self.author == "":
+            self.author = self.email

       # Save the In-Reply-To:, References:, and Message-ID: lines
        #
@@ -197,8 +200,10 @@
            self.in_reply_to = ''
       else:
           match = msgid_pat.search(i_r_t)
-           if match is None: self.in_reply_to = ''
-           else: self.in_reply_to = strip_separators(match.group(1))
+           if match is None:
+                self.in_reply_to = ''
+           else:
+                self.in_reply_to = strip_separators(match.group(1))

       references = message.getheader('References')
       if references is None:
@@ -352,7 +357,7 @@
                                                   refs[0])
                for ref in refs[1:]:
                    a = self.database.getArticle(self.archive, ref)
-                    if a.date > maxdate.data:
+                    if a.date > maxdate.date:
                        maxdate = a
                parentID = maxdate.msgid
           else:
Index: Mailman/Bouncers/BouncerAPI.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Bouncers/BouncerAPI.py,v
retrieving revision 1.11
retrieving revision 1.11.2.1
diff -u -r1.11 -r1.11.2.1
--- Mailman/Bouncers/BouncerAPI.py      2000/09/21 04:50:10     1.11
+++ Mailman/Bouncers/BouncerAPI.py      2001/07/10 15:00:09     1.11.2.1
@@ -82,6 +82,7 @@

# for testing
if __name__ == '__main__':
+    import sys
    import mimetools
    from Mailman import MailList

Index: Mailman/Bouncers/DSN.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Bouncers/DSN.py,v
retrieving revision 1.7
retrieving revision 1.7.2.1
diff -u -r1.7 -r1.7.2.1
--- Mailman/Bouncers/DSN.py     2000/07/21 05:25:53     1.7
+++ Mailman/Bouncers/DSN.py     2001/07/25 18:04:42     1.7.2.1
@@ -1,4 +1,4 @@
-# Copyright (C) 1998,1999,2000 by the Free Software Foundation, Inc.
+# Copyright (C) 1998,1999,2000,2001 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
@@ -43,8 +43,8 @@


def process(msg):
-    if msg.gettype() <> 'multipart/report' or \
-       msg.getparam('report-type') <> 'delivery-status':
+    if string.lower(msg.gettype()) <> 'multipart/report' or \
+       string.lower(msg.getparam('report-type')) <> 'delivery-status':
        # then
        return None
    boundary = msg.getparam('boundary')
Index: Mailman/Cgi/handle_opts.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Cgi/Attic/handle_opts.py,v
retrieving revision 1.30.2.2
retrieving revision 1.30.2.3
diff -u -r1.30.2.2 -r1.30.2.3
--- Mailman/Cgi/handle_opts.py  2001/05/03 21:05:06     1.30.2.2
+++ Mailman/Cgi/handle_opts.py  2001/07/10 14:52:32     1.30.2.3
@@ -266,14 +266,14 @@
        except Errors.MMNotAMemberError:
            PrintResults(mlist, operation, doc,
                         "%s isn't subscribed to this list."
-                         % mail.GetSender(), user)
+                         % user, user)
        except Errors.MMListNotReadyError:
            PrintResults(mlist, operation, doc, "List is not functional.",
                         user)
        except Errors.MMNoSuchUserError:
            PrintResults(mlist, operation, doc,
                         "%s is not subscribed to this list."
-                         % mail.GetSender(), user)
+                         % user, user)
        except Errors.MMBadPasswordError:
            PrintResults(mlist, operation, doc,
                         "You gave the wrong password.", user)
Index: Mailman/Handlers/Hold.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Handlers/Hold.py,v
retrieving revision 1.16
retrieving revision 1.16.2.2
diff -u -r1.16 -r1.16.2.2
--- Mailman/Handlers/Hold.py    2000/08/01 23:02:28     1.16
+++ Mailman/Handlers/Hold.py    2001/05/31 21:05:44     1.16.2.2
@@ -1,4 +1,4 @@
-# Copyright (C) 1998,1999,2000 by the Free Software Foundation, Inc.
+# Copyright (C) 1998,1999,2000,2001 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
@@ -118,6 +118,11 @@
    if not sender or sender[:len(listname)+6] == adminaddr:
        sender = msg.GetSender(use_envelope=0)
    #
+    # possible administrivia?
+    if mlist.administrivia and Utils.IsAdministrivia(msg):
+        hold_for_approval(mlist, msg, msgdata, Administrivia)
+        # no return
+    #
    # is the poster in the list of explicitly forbidden posters?
    if len(mlist.forbidden_posters):
        forbiddens = Utils.List2Dict(mlist.forbidden_posters)
@@ -175,11 +180,6 @@
       not msgdata.get('fromusenet'):
        # then
        hold_for_approval(mlist, msg, msgdata, ImplicitDestination)
-        # no return
-    #
-    # possible administrivia?
-    if mlist.administrivia and Utils.IsAdministrivia(msg):
-        hold_for_approval(mlist, msg, msgdata, Administrivia)
        # no return
    #
    # suspicious headers?
Index: admin/www/download.ht
===================================================================
RCS file: /cvsroot/mailman/mailman/admin/www/download.ht,v
retrieving revision 1.5.2.6
retrieving revision 1.5.2.7
diff -u -r1.5.2.6 -r1.5.2.7
--- admin/www/download.ht       2001/05/03 21:09:36     1.5.2.6
+++ admin/www/download.ht       2001/07/25 18:08:31     1.5.2.7
@@ -65,9 +65,9 @@
<h3>Downloading</h3>

<p>Version
-(<!-VERSION--->2.0.5<!-VERSION--->,
+(<!-VERSION--->2.0.6<!-VERSION--->,
released on
-<!-DATE--->May  4 2001<!-DATE--->)
+<!-DATE--->Jul 25 2001<!-DATE--->)
is the current GNU release.  It is available from the following mirror sites:

<ul>
Index: admin/www/download.html
===================================================================
RCS file: /cvsroot/mailman/mailman/admin/www/download.html,v
retrieving revision 1.6.2.8
retrieving revision 1.6.2.9
diff -u -r1.6.2.8 -r1.6.2.9
--- admin/www/download.html     2001/05/03 21:09:36     1.6.2.8
+++ admin/www/download.html     2001/07/25 18:08:31     1.6.2.9
@@ -1,6 +1,6 @@
<HTML>
<!-- THIS PAGE IS AUTOMATICALLY GENERATED.  DO NOT EDIT. -->
-<!-- Thu May  3 17:09:03 2001 -->
+<!-- Wed Jul 25 14:08:14 2001 -->
<!-- USING HT2HTML 1.1 -->
<!-- SEE http://www.wooz.org/barry/software/pyware.html -->
<!-- User-specified headers:
@@ -237,9 +237,9 @@
<h3>Downloading</h3>

<p>Version
-(<!-VERSION--->2.0.5<!-VERSION--->,
+(<!-VERSION--->2.0.6<!-VERSION--->,
released on
-<!-DATE--->May  4 2001<!-DATE--->)
+<!-DATE--->Jul 25 2001<!-DATE--->)
is the current GNU release.  It is available from the following mirror sites:

<ul>
Index: bin/find_member
===================================================================
RCS file: /cvsroot/mailman/mailman/bin/find_member,v
retrieving revision 1.5
retrieving revision 1.5.2.1
diff -u -r1.5 -r1.5.2.1
--- bin/find_member     2000/09/11 03:58:57     1.5
+++ bin/find_member     2001/07/25 17:38:43     1.5.2.1
@@ -90,7 +90,7 @@
        try:
            mlist = MailList.MailList(listname, lock=0)
        except Errors.MMListError:
-            print 'No such list "%s"' % name
+            print 'No such list "%s"' % listname
            continue
        if options.owners:
            owners = mlist.owner
Index: src/cgi-wrapper.c
===================================================================
RCS file: /cvsroot/mailman/mailman/src/cgi-wrapper.c,v
retrieving revision 1.13
retrieving revision 1.13.2.1
diff -u -r1.13 -r1.13.2.1
--- src/cgi-wrapper.c   2000/03/21 06:26:41     1.13
+++ src/cgi-wrapper.c   2001/05/29 13:20:27     1.13.2.1
@@ -23,7 +23,7 @@

/* passed in by configure */
#define SCRIPTNAME  SCRIPT
-#define LOG_IDENT   "Mailman cgi-wrapper (" ## SCRIPT ## ")"
+#define LOG_IDENT   "Mailman cgi-wrapper (" SCRIPT ")"

/* GID that CGI scripts run as.  See your Web server's documentation. */
#define LEGAL_PARENT_GID CGI_GID
Index: src/common.c
===================================================================
RCS file: /cvsroot/mailman/mailman/src/common.c,v
retrieving revision 1.26
retrieving revision 1.26.2.1
diff -u -r1.26 -r1.26.2.1
--- src/common.c        2000/11/09 06:18:02     1.26
+++ src/common.c        2001/05/29 13:20:27     1.26.2.1
@@ -20,7 +20,7 @@
#include "common.h"

/* passed in by configure */
-#define SCRIPTDIR PREFIX ## "/scripts/"             /* trailing slash */
+#define SCRIPTDIR PREFIX "/scripts/"        /* trailing slash */
#define MODULEDIR PREFIX                    /* no trailing slash */

const char* scriptdir = SCRIPTDIR;