[Mailman-Developers] Using mailman with the secure-linux kernel patch

Marc MERLIN mailman-users@python.org, marc_news@valinux.com
Thu, 5 Oct 2000 10:19:13 -0700


[mailman-developers@python.org Cced in case they want to add my shell script to
the tree, but followup set to mailman-users@python.org]

I wanted to have mailman run on my servers that have the secure-linux kernel
patch. I ended up  writing a small shell script that  changed permissions so
that  scripts ran  as UID  mailman (by  making sure  that scripts  that lock
config.db do so with UID mailman).
I later realized that python doesn't  seem to have a suidpython wrapper like
perl does, so I  scrapped the shell script and attempted to  put a few lines
of python together to modify some scripts in mailman/bin so that they change
their uid  to mailman  if root  runs them  or complain  that they  can't run
unless their uid is mailman.

Please let  me know if  I forgot  to chmod or  modify other files  that lock
config.db:
binfilestopatch= ( 'add_members', 'check_db', 'clone_member', 'config_list',
'move_list', 'newlist', 'remove_members', 'rmlist', 'sync_members',
'update', 'withlist' )

It'd  be  nice  if  that  script  were  included  as  unsupported  with  the
mailman tree  so that people  who really want  to have the  protections from
secure-linux, can still run mailman.
If someone needs to make minor modifications to the script before including
it, I'm cool with that.

Thanks,
Marc

~mailman/bin/fix_perms.securelinux
----------------------------------------------------------------------------
#! /usr/bin/env python
#
# Copyright (C) 1998,1999,2000 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.

"""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.db files) are SUID
mailman.
The idea  is that config.db 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  %(PROGRAM) -f,
which applies the necessary permission fixes
 
As a  result, to  prevent anyone from  running priviledged  mailman commands
(since the  scripts are suid), binary  commands that are changed  to be SUID
are also unreadable and unrunable 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/04
"""

import sys
import os
import paths
import re

# 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():
    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 pwd
import os

class CheckFixUid:
    mailmanuid=pwd.getpwnam("mailman")[2]
    if os.geteuid() == 0:
	os.setuid(mailmanuid)
    if os.geteuid() != mailmanuid:
	print "You need to run this script as root or mailman because it was configured to run\non a linux system with the secure-linux patch which restricts hard links"
	sys.exit()
""")
	fp.close
    else:
	print "Skipping creation of "+droplib


    print "Making cgis setuid mailman"
    os.system('chmod 6755 '+paths.prefix+'/cgi-bin/*')

    print "Making mail wrapper setuid mailman"
    os.system('chmod 6755 '+paths.prefix+'/mail/wrapper')

    print "Ensuring that all config.db fiels are owned by Mailman"
    os.system('chown mailman.mailman '+paths.prefix+'/lists/*/config.db*')

    print "Patching 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.\nIf you use it, mailman may not function properly"
	    else:
		filefd=open(script, "w")
		filefd.writelines(file)
	    
main(sys.argv)
----------------------------------------------------------------------------

-- 
Microsoft is to software what McDonalds is to gourmet cooking
 
Home page: http://marc.merlins.org/ (friendly to non IE browsers)
Finger marc_f@merlins.org for PGP key and other contact information