Scott Berry wrote: > Tod could you send me a copy of your check_perms please. I tried > changing that but it still provides me with the same error. It's attached. You can check that the only difference in the attached file and the installed is the _( change by using diff. That way you don't have to worry that I've slipped in something nefarious. diff -u /usr/lib/mailman/bin/check_perms /path/to/attached/check_perms The ouput should look like this: --- check_perms~ 2007-01-29 09:20:43.000000000 -0500 +++ check_perms 2007-07-08 12:09:34.000000000 -0400 @@ -213,7 +213,7 @@ # In addition, on a multiuser system you may want to hide the private # archives so other users can't read them. if mode & S_IXOTH: - print _("""\ + print C_("""\ Warning: Private archive directory is other-executable (o+x). This could allow other users on your system to read private archives. If you're on a shared multiuser system, you should consult the The minus represents lines from the original file, the plus is for lines from the new file. > Also what permission is check_perms supposed to be set at? It should be 755, owner root, group mailman. You can check what it should be using rpm like so: $ rpm -qlv mailman | grep /usr/lib/mailman/bin/check_perms -rwxr-xr-x 1 root mailman 12904 Jan 29 09:20 /usr/lib/mailman/bin/check_perms If you're using SELinux you should be careful if you copy the attached file that the security contexts get set properly. I'm sure there are a few ways to do this. I think one of the easier ways is: # restorecon -v /usr/lib/mailman/bin/check_perms And, if you're using SELinux, there may be other issues you'll run into while getting mailman and postfix integrated. I did when I tried a quick test in FC6. I didn't take the time to resolve those issues then because I was only doing some quick testing. The production systems I have using mailman have not yet been upgraded to anything new enough to have SELinux on them yet. (They will be soon though and I'm planning to work out whatever issues I have then so that I can keep SELinux enabled.) -- Todd OpenPGP -> KeyID: 0xBEAF0CE3 | URL: www.pobox.com/~tmz/pgp ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sometimes I think I understand everything, then I regain consciousness.
#! /usr/bin/python # # Copyright (C) 1998-2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """Check the permissions for the Mailman installation. Usage: %(PROGRAM)s [-f] [-v] [-h] With no arguments, just check and report all the files that have bogus permissions or group ownership. With -f (and run as root), fix all the permission problems found. With -v be verbose. """ import os import sys import pwd import grp import errno import getopt from stat import * try: import paths except ImportError: print '''Could not import paths! This probably means that you are trying to run check_perms from the source directory. You must run this from the installation directory instead. ''' raise from Mailman import mm_cfg from Mailman.mm_cfg import MAILMAN_USER, MAILMAN_GROUP from Mailman.i18n import C_ # Let KeyErrors percolate MAILMAN_GID = grp.getgrnam(MAILMAN_GROUP)[2] MAILMAN_UID = pwd.getpwnam(MAILMAN_USER)[2] PROGRAM = sys.argv[0] # Gotta check the archives/private/*/database/* files try: True, False except NameError: True = 1 False = 0 class State: FIX = False VERBOSE = False ERRORS = 0 STATE = State() DIRPERMS = S_ISGID | S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH QFILEPERMS = S_ISGID | S_IRWXU | S_IRWXG PYFILEPERMS = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ARTICLEFILEPERMS = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP def statmode(path): return os.stat(path)[ST_MODE] def statgidmode(path): stat = os.stat(path) return stat[ST_MODE], stat[ST_GID] seen = {} # libc's getgrgid re-opens /etc/group each time :( _gidcache = {} def getgrgid(gid): data = _gidcache.get(gid) if data is None: data = grp.getgrgid(gid) _gidcache[gid] = data return data def checkwalk(arg, dirname, names): # Short-circuit duplicates if seen.has_key(dirname): return seen[dirname] = True for name in names: path = os.path.join(dirname, name) if arg.VERBOSE: print C_(' checking gid and mode for %(path)s') try: mode, gid = statgidmode(path) except OSError, e: if e.errno <> errno.ENOENT: raise continue if gid <> MAILMAN_GID: try: groupname = getgrgid(gid)[0] except KeyError: groupname = '<anon gid %d>' % gid arg.ERRORS += 1 print C_('%(path)s bad group (has: %(groupname)s, ' 'expected %(MAILMAN_GROUP)s)'), if STATE.FIX: print C_('(fixing)') os.chown(path, -1, MAILMAN_GID) else: print # all directories must be at least rwxrwsr-x. Don't check the private # archive directory or database directory themselves since these are # checked in checkarchives() and checkarchivedbs() below. private = mm_cfg.PRIVATE_ARCHIVE_FILE_DIR if path == private or (os.path.commonprefix((path, private)) == private and os.path.split(path)[1] == 'database'): continue # The directories under qfiles should have a more limited permission if os.path.commonprefix((path, mm_cfg.QUEUE_DIR)) == mm_cfg.QUEUE_DIR: targetperms = QFILEPERMS octperms = oct(targetperms) else: targetperms = DIRPERMS octperms = oct(targetperms) if S_ISDIR(mode) and (mode & targetperms) <> targetperms: arg.ERRORS += 1 print C_('directory permissions must be %(octperms)s: %(path)s'), if STATE.FIX: print C_('(fixing)') os.chmod(path, mode | targetperms) else: print elif os.path.splitext(path)[1] in ('.py', '.pyc', '.pyo'): octperms = oct(PYFILEPERMS) if mode & PYFILEPERMS <> PYFILEPERMS: print C_('source perms must be %(octperms)s: %(path)s'), arg.ERRORS += 1 if STATE.FIX: print C_('(fixing)') os.chmod(path, mode | PYFILEPERMS) else: print elif path.endswith('-article'): # Article files must be group writeable octperms = oct(ARTICLEFILEPERMS) if mode & ARTICLEFILEPERMS <> ARTICLEFILEPERMS: print C_('article db files must be %(octperms)s: %(path)s'), arg.ERRORS += 1 if STATE.FIX: print C_('(fixing)') os.chmod(path, mode | ARTICLEFILEPERMS) else: print def checkall(): # first check PREFIX if STATE.VERBOSE: prefix = mm_cfg.PREFIX print C_('checking mode for %(prefix)s') dirs = {} for d in (mm_cfg.PREFIX, mm_cfg.EXEC_PREFIX, mm_cfg.VAR_PREFIX, mm_cfg.CONFIG_DIR, mm_cfg.DATA_DIR, mm_cfg.LOCK_DIR, mm_cfg.LOG_DIR, mm_cfg.QUEUE_DIR, mm_cfg.PID_DIR): dirs[d] = True for d in dirs.keys(): try: mode = statmode(d) except OSError, e: if e.errno <> errno.ENOENT: raise print C_('WARNING: directory does not exist: %(d)s') continue if (mode & DIRPERMS) <> DIRPERMS: STATE.ERRORS += 1 print C_('directory must be at least 02775: %(d)s'), if STATE.FIX: print C_('(fixing)') os.chmod(d, mode | DIRPERMS) else: print # check all subdirs os.path.walk(d, checkwalk, STATE) def checkarchives(): private = mm_cfg.PRIVATE_ARCHIVE_FILE_DIR if STATE.VERBOSE: print C_('checking perms on %(private)s') # private archives must not be other readable mode = statmode(private) if mode & S_IROTH: STATE.ERRORS += 1 print C_('%(private)s must not be other-readable'), if STATE.FIX: print C_('(fixing)') os.chmod(private, mode & ~S_IROTH) else: print # In addition, on a multiuser system you may want to hide the private # archives so other users can't read them. if mode & S_IXOTH: print C_("""\ Warning: Private archive directory is other-executable (o+x). This could allow other users on your system to read private archives. If you're on a shared multiuser system, you should consult the installation manual on how to fix this.""") MBOXPERMS = S_IRGRP | S_IWGRP | S_IRUSR | S_IWUSR def checkmboxfile(mboxdir): absdir = os.path.join(mm_cfg.PRIVATE_ARCHIVE_FILE_DIR, mboxdir) for f in os.listdir(absdir): if not f.endswith('.mbox'): continue mboxfile = os.path.join(absdir, f) mode = statmode(mboxfile) if (mode & MBOXPERMS) <> MBOXPERMS: STATE.ERRORS = STATE.ERRORS + 1 print C_('mbox file must be at least 0660:'), mboxfile if STATE.FIX: print C_('(fixing)') os.chmod(mboxfile, mode | MBOXPERMS) else: print def checkarchivedbs(): # The archives/private/listname/database file must not be other readable # or executable otherwise those files will be accessible when the archives # are public. That may not be a horrible breach, but let's close this off # anyway. for dir in os.listdir(mm_cfg.PRIVATE_ARCHIVE_FILE_DIR): if dir.endswith('.mbox'): checkmboxfile(dir) dbdir = os.path.join(mm_cfg.PRIVATE_ARCHIVE_FILE_DIR, dir, 'database') try: mode = statmode(dbdir) except OSError, e: if e.errno not in (errno.ENOENT, errno.ENOTDIR): raise continue if mode & S_IRWXO: STATE.ERRORS += 1 print C_('%(dbdir)s "other" perms must be 000'), if STATE.FIX: print C_('(fixing)') os.chmod(dbdir, mode & ~S_IRWXO) else: print def checkcgi(): cgidir = os.path.join(mm_cfg.EXEC_PREFIX, 'cgi-bin') if STATE.VERBOSE: print C_('checking cgi-bin permissions') exes = os.listdir(cgidir) for f in exes: path = os.path.join(cgidir, f) if STATE.VERBOSE: print C_(' checking set-gid for %(path)s') mode = statmode(path) if mode & S_IXGRP and not mode & S_ISGID: STATE.ERRORS += 1 print C_('%(path)s must be set-gid'), if STATE.FIX: print C_('(fixing)') os.chmod(path, mode | S_ISGID) else: print def checkmail(): wrapper = os.path.join(mm_cfg.WRAPPER_DIR, 'mailman') if STATE.VERBOSE: print C_('checking set-gid for %(wrapper)s') mode = statmode(wrapper) if not mode & S_ISGID: STATE.ERRORS += 1 print C_('%(wrapper)s must be set-gid'), if STATE.FIX: print C_('(fixing)') os.chmod(wrapper, mode | S_ISGID) def checkadminpw(): for pwfile in (os.path.join(mm_cfg.DATA_DIR, 'adm.pw'), os.path.join(mm_cfg.DATA_DIR, 'creator.pw')): targetmode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP if STATE.VERBOSE: print C_('checking permissions on %(pwfile)s') try: mode = statmode(pwfile) except OSError, e: if e.errno <> errno.ENOENT: raise return if mode <> targetmode: STATE.ERRORS += 1 octmode = oct(mode) print C_('%(pwfile)s permissions must be exactly 0640 ' '(got %(octmode)s)'), if STATE.FIX: print C_('(fixing)') os.chmod(pwfile, targetmode) else: print def checkmta(): if mm_cfg.MTA: modname = 'Mailman.MTA.' + mm_cfg.MTA __import__(modname) try: sys.modules[modname].checkperms(STATE) except AttributeError: pass def checkdata(): targetmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP checkfiles = ('config.pck', 'config.pck.last', 'config.db', 'config.db.last', 'next-digest', 'next-digest-topics', 'request.db', 'request.db.tmp') if STATE.VERBOSE: print C_('checking permissions on list data') # BAW: This needs to be converted to the Site module abstraction for dir in os.listdir(mm_cfg.LIST_DATA_DIR): for file in checkfiles: path = os.path.join(mm_cfg.LIST_DATA_DIR, dir, file) if STATE.VERBOSE: print C_(' checking permissions on: %(path)s') try: mode = statmode(path) except OSError, e: if e.errno <> errno.ENOENT: raise continue if (mode & targetmode) <> targetmode: STATE.ERRORS += 1 print C_('file permissions must be at least 660: %(path)s'), if STATE.FIX: print C_('(fixing)') os.chmod(path, mode | targetmode) else: print def usage(code, msg=''): if code: fd = sys.stderr else: fd = sys.stdout print >> fd, C_(__doc__) if msg: print >> fd, msg sys.exit(code) if __name__ == '__main__': try: opts, args = getopt.getopt(sys.argv[1:], 'fvh', ['fix', 'verbose', 'help']) except getopt.error, msg: usage(1, msg) for opt, arg in opts: if opt in ('-h', '--help'): usage(0) elif opt in ('-f', '--fix'): STATE.FIX = True elif opt in ('-v', '--verbose'): STATE.VERBOSE = True checkall() checkarchives() checkarchivedbs() checkcgi() checkmail() checkdata() checkadminpw() checkmta() if not STATE.ERRORS: print C_('No problems found') else: print C_('Problems found:'), STATE.ERRORS print C_('Re-run as %(MAILMAN_USER)s (or root) with -f flag to fix')
Attachment:
pgp2y9KM2ENIO.pgp
Description: PGP signature