[Mailman-Developers] Patch: securelinux_fix update (now check_perms_grsecurity)

Marc MERLIN marc_news@valinux.com
Mon, 10 Dec 2001 01:07:10 -0800


I've updated  the docs, updated my  script to work with  grsecurity and with
the new scripts in mailman cvs, and I've renamed it to reflect the changes


diff -urN mailman.orig/README.LINUX mailman/README.LINUX
--- mailman.orig/README.LINUX	Mon Dec 10 01:00:52 2001
+++ mailman/README.LINUX	Mon Dec 10 01:03:19 2001
@@ -8,18 +8,12 @@
     GNU/Linux seems to be the most popular platform on which to run
     Mailman.  Here are some hints on getting Mailman to run on Linux:
 
-    If you are running secure_linux, you probably have restricted
-    hardlinks turned on.  Gergely Madarasz says that this not only
-    restricts hardlinks in /tmp, but also in any non +t directory.  This
-    can cause "Operation not permitted" errors in MailList.Save() -- you
-    will see a traceback.  You must turn restricted hardlinks off.  This
-    is also known under the name of Openwall Security Patches.
-
-    There is a workaround for this problem, you can use securelinux_fix.py
-    in the contrib directory (see the README.securelinux_fix.py). Note
-    that the script will not work until you move it in your installed
-    Mailman tree in the bin directory.
+    If you are getting errors with hard link creations and/or you are using
+    a special secure kernel (securelinux/openwall/grsecurity), see
+    contrib/README.check_perms_grsecurity.
 
+    Note that if you are using Linux Mandrake in secure mode, you are probably
+    concerned by this
 
 
 Local Variables:
diff -urN mailman.orig/contrib/README.check_perms_grsecurity mailman/contrib/README.check_perms_grsecurity
--- mailman.orig/contrib/README.check_perms_grsecurity	Wed Dec 31 16:00:00 1969
+++ mailman/contrib/README.check_perms_grsecurity	Mon Dec 10 01:00:08 2001
@@ -0,0 +1,14 @@
+The check_perms_grsecurity.py script, if copied in your installed
+~mailman/bin/ directory and run from there will modify permissions of
+files so that Mailman with extra restrictions imposed by linux kernel security
+patches like securelinux/openwall in 2.2.x or grsecurity in 2.4.x
+
+The way it works is that it makes sure that the UID of any script that
+touches config.pck is `mailman'. What this means however is that
+scripts in ~mailman/bin will now only work if run as user mailman or
+root (the script then changes its UID and GID to mailman).
+To make grsecurity happy, we remove the group writeable bit on a directories
+that contain binaries
+
+Enjoy
+Marc MERLIN <marc_soft@merlins.org>/<marc_bts@vasoftware.com> - 2001/12/10
diff -urN mailman.orig/contrib/README.securelinux_fix mailman/contrib/README.securelinux_fix
--- mailman.orig/contrib/README.securelinux_fix	Mon Mar 12 11:28:45 2001
+++ mailman/contrib/README.securelinux_fix	Wed Dec 31 16:00:00 1969
@@ -1,12 +0,0 @@
-The securelinux_fix.py script, if copied in your installed
-~mailman/bin/ directory and run from there will modify permissions of
-files so that Mailman works despite the securelinux (aka openwall)
-symbolic and hard link restrictions.
-
-The way it works is that it makes sure that the UID of any script that
-touches config.db is `mailman'. What this means however is that
-scripts in ~mailman/bin will now only work if run as user mailman or
-root (the script then changes its UID and GID to mailman).
-
-Enjoy
-Marc MERLIN <marcsoft@merlins.org>/<marc_bts@valinux.com>
diff -urN mailman.orig/contrib/check_perms_grsecurity.py mailman/contrib/check_perms_grsecurity.py
--- mailman.orig/contrib/check_perms_grsecurity.py	Wed Dec 31 16:00:00 1969
+++ mailman/contrib/check_perms_grsecurity.py	Mon Dec 10 00:56:55 2001
@@ -0,0 +1,173 @@
+#! @PYTHON@
+#
+# 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
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software 
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+"""Fixes for running Mailman under the `secure-linux' patch or grsecurity.
+
+Run check_perms -f and only then check_perms_grsecurity.py -f
+Note that you  will have to re-run  this script after a  mailman upgrade and
+that check_perms will undo part of what this script does
+
+If you use  Solar Designer's secure-linux patch, it prevents  a process from
+linking (hard link) to a file it doesn't own.
+Grsecurity (http://grsecurity.net/) can have  the same restriction depending
+on how it was built, including other restrictions like preventing you to run
+a program if it is located in a directory writable by a non root user.
+
+As a  result Mailman has to  be changed so that  the whole tree is  owned by
+Mailman, and  the CGIs and some  of the programs  in the bin tree  (the ones
+that lock config.pck  files) are SUID Mailman.  The idea  is that config.pck
+files have to be owned by the  mailman UID and only touched by programs that
+are UID mailman.
+At the  same time, We have  to make sure  that at least 3  directories under
+~mailman aren't writable by mailman: mail, cgi-bin, and bin
+ 
+Binary commands that are changed to be SUID mailman are also made unreadable
+and unrunnable  by people who aren't  in the mailman group.   This shouldn't
+affect much since most of those commands would fail work if you weren't part
+of the mailman group anyway.
+Scripts in ~mailman/bin/ are  not made suid or sgid, they need  to be run by
+user mailman or root to work.
+
+Marc <marc_soft@merlins.org>/<marc_bts@vasoftware.com> 
+2000/10/27 - Initial version for secure_linux/openwall and mailman 2.0
+2001/12/09 - Updated version for grsecurity and mailman 2.1
+"""
+
+import sys
+import os
+import paths
+import re
+import glob
+from Mailman import mm_cfg
+from Mailman.mm_cfg import MAILMAN_UID, MAILMAN_GID
+from stat import *
+
+# Directories that we don't want writable by mailman.
+dirstochownroot= ( 'mail', 'cgi-bin', 'bin' )
+
+# Those are the programs that we patch so that they insist being run under the
+# mailman uid or as root.
+binfilestopatch= ( 'add_members', 'change_pw', 'check_db', 'clone_member', 
+	'config_list', 'newlist', 'qrunner', 'remove_members', 
+	'rmlist', 'sync_members', 'update', 'withlist' )
+
+def main(argv):
+    binpath = paths.prefix + '/bin/'
+    droplib = binpath + 'CheckFixUid.py'
+
+    if len(argv) < 2 or argv[1] != "-f":
+	print __doc__
+	sys.exit(1)
+
+    print "Making select directories owned and writable by root only"
+    for dir in dirstochownroot:
+	dirpath = paths.prefix + '/' + dir
+	os.chown(dirpath, 0, MAILMAN_GID)
+	os.chmod(dirpath, 02755)
+	print dirpath
+
+    print
+
+    file = paths.prefix + '/data/last_mailman_version'
+    print "Making" + file + "owned by mailman (not root)"
+    os.chown(file, MAILMAN_UID, MAILMAN_GID)
+    print
+
+    if not os.path.exists(droplib):
+	print "Creating " + droplib
+	fp = open(droplib, 'w', 0644)
+	fp.write("""import sys
+import os
+from Mailman.mm_cfg import MAILMAN_UID, MAILMAN_GID
+
+class CheckFixUid:
+    if os.geteuid() == 0:
+	os.setgid(MAILMAN_GID)
+	os.setuid(MAILMAN_UID)
+    if os.geteuid() != MAILMAN_UID:
+	print "You need to run this script as root or mailman because it was configured to run"
+	print "on a linux system with a security patch which restricts hard links"
+	sys.exit()
+""")
+	fp.close()
+    else:
+	print "Skipping creation of " + droplib
+
+
+    print "\nMaking cgis setuid mailman"
+    cgis = glob.glob(paths.prefix + '/cgi-bin/*')
+    
+    for file in cgis:
+	print file
+	os.chown(file, MAILMAN_UID, MAILMAN_GID)
+	os.chmod(file, 06755)
+
+    print "\nMaking mail wrapper setuid mailman"
+    file= paths.prefix + '/mail/wrapper'
+    os.chown(file, MAILMAN_UID, MAILMAN_GID)
+    os.chmod(file, 06755)
+    print file
+
+    print "\nEnsuring that all config.db/pck files are owned by Mailman"
+    cdbs = glob.glob(paths.prefix + '/lists/*/config.db*')
+    cpcks = glob.glob(paths.prefix + '/lists/*/config.pck*')
+
+    for file in cdbs + cpcks:
+	stat = os.stat(file)
+	if (stat[ST_UID] != MAILMAN_UID or stat[ST_GID] != MAILMAN_GID):
+	    print file
+	    os.chown(file, MAILMAN_UID, MAILMAN_GID)
+    
+    print "\nPatching mailman scripts to change the uid to mailman"
+
+    for script in binfilestopatch:
+	filefd = open(script, "r")
+	file = filefd.readlines()
+	filefd.close()
+
+	patched = 0
+	try:
+	    file.index("import CheckFixUid\n")
+	    print "Not patching " + script + ", already patched"
+	except ValueError:
+	    file.insert(file.index("import paths\n")+1, "import CheckFixUid\n")
+	    for i in range(len(file)-1, 0, -1):
+		object=re.compile("^([	 ]*)main\(").search(file[i])
+		# Special hack to support patching of update
+		object2=re.compile("^([	    ]*).*=[	 ]*main\(").search(file[i])
+		if object:
+		    print "Patching " + script
+		    file.insert(i, 
+			object.group(1) + "CheckFixUid.CheckFixUid()\n")
+		    patched=1
+		    break
+		if object2:
+		    print "Patching " + script
+		    file.insert(i, 
+			object2.group(1) + "CheckFixUid.CheckFixUid()\n")
+		    patched=1
+		    break
+
+	    if patched==0:
+		print "Warning, file "+script+" couldn't be patched."
+		print "If you use it, mailman may not function properly"
+	    else:
+		filefd=open(script, "w")
+		filefd.writelines(file)
+	    
+main(sys.argv)
diff -urN mailman.orig/contrib/securelinux_fix.py mailman/contrib/securelinux_fix.py
--- mailman.orig/contrib/securelinux_fix.py	Thu Oct  4 07:45:36 2001
+++ mailman/contrib/securelinux_fix.py	Wed Dec 31 16:00:00 1969
@@ -1,134 +0,0 @@
-#! @PYTHON@
-#
-# 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
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software 
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-"""Fixes for running Mailman under the `secure-linux' patch.
-
-If you use Solar Designer's secure-linux patch, it prevents a process from
-linking (hard link) to a file it doesn't own.  As a result Mailman has to be
-changed so that the whole tree is owned by Mailman, and the CGIs and some of
-the programs in the bin tree (the ones that lock config.pck files) are SUID
-Mailman.  The idea is that config.pck files have to be owned by the mailman
-UID and only touched by programs that are UID mailman.
- 
-If you have to run check_perms -f, make sure to also run securelinux_fix.py
--f, which applies the necessary permission fixes.
- 
-As a result, to prevent anyone from running privileged Mailman commands (since
-the scripts are suid), binary commands that are changed to be SUID are also
-unreadable and unrunnable by people who aren't in the mailman group.  This
-shouldn't affect much since most of those commands would fail work if you
-weren't part of the mailman group anyway.
-
-Marc <marcsoft@merlins.org>/<marc_bts@valinux.com> 2000/10/27
-"""
-
-import sys
-import os
-import paths
-import re
-import glob
-from Mailman import mm_cfg
-from Mailman.mm_cfg import MAILMAN_UID, MAILMAN_GID
-from stat import *
-
-# Those are the programs that we patch so that they insist being run under the
-# mailman uid or as root.
-binfilestopatch= ( 'add_members', 'check_db', 'clone_member', 
-	'config_list', 'move_list', 'newlist', 'remove_members', 'rmlist', 
-	'sync_members', 'update', 'withlist' )
-
-def main(argv):
-    binpath = paths.prefix + '/bin/'
-    droplib = binpath + 'CheckFixUid.py'
-
-    if len(argv) < 2 or argv[1] != "-f":
-	print __doc__
-	sys.exit(1)
-
-    if not os.path.exists(droplib):
-	print "Creating " + droplib
-	fp = open(droplib, 'w', 0644)
-	fp.write("""import sys
-import os
-from Mailman.mm_cfg import MAILMAN_UID, MAILMAN_GID
-
-class CheckFixUid:
-    if os.geteuid() == 0:
-	os.setgid(MAILMAN_GID)
-	os.setuid(MAILMAN_UID)
-    if os.geteuid() != MAILMAN_UID:
-	print "You need to run this script as root or mailman because it was configured to run"
-	print "on a linux system with the secure-linux patch which restricts hard links"
-	sys.exit()
-""")
-	fp.close()
-    else:
-	print "Skipping creation of " + droplib
-
-
-    print "\nMaking cgis setuid mailman"
-    cgis = glob.glob(paths.prefix + '/cgi-bin/*')
-    
-    for file in cgis:
-	print file
-	os.chown(file, MAILMAN_UID, MAILMAN_GID)
-	os.chmod(file, 06755)
-
-    print "\nMaking mail wrapper setuid mailman"
-    os.chown(paths.prefix + '/mail/wrapper', MAILMAN_UID, MAILMAN_GID)
-    os.chmod(paths.prefix + '/mail/wrapper', 06755)
-
-    print "\nEnsuring that all config.pck files are owned by Mailman"
-    cdbs = glob.glob(paths.prefix + '/lists/*/config.pck*')
-
-    for file in cdbs:
-	stat = os.stat(file)
-	if (stat[ST_UID] != MAILMAN_UID or stat[ST_GID] != MAILMAN_GID):
-	    print file
-	    os.chown(file, MAILMAN_UID, MAILMAN_GID)
-    
-    print "\nPatching mailman scripts to change the uid to mailman"
-
-    for script in binfilestopatch:
-	filefd = open(script, "r")
-	file = filefd.readlines()
-	filefd.close()
-
-	patched = 0
-	try:
-	    file.index("import CheckFixUid\n")
-	    print "Not patching " + script + ", already patched"
-	except ValueError:
-	    file.insert(file.index("import paths\n")+1, "import CheckFixUid\n")
-	    for i in range(len(file)-1, 0, -1):
-		object=re.compile("^([	 ]*)main\(").search(file[i])
-		if object:
-		    print "Patching " + script
-		    file.insert(i, 
-			object.group(1) + "CheckFixUid.CheckFixUid()\n")
-		    patched=1
-		    break
-
-	    if patched==0:
-		print "Warning, file "+script+" couldn't be patched."
-		print "If you use it, mailman may not function properly"
-	    else:
-		filefd=open(script, "w")
-		filefd.writelines(file)
-	    
-main(sys.argv)
-- 
Microsoft is to operating systems & security ....
                                      .... what McDonalds is to gourmet cooking
  
Home page: http://marc.merlins.org/   |   Finger marc_f@merlins.org for PGP key