diff options
| author | bwarsaw | 2006-09-24 16:49:18 +0000 |
|---|---|---|
| committer | bwarsaw | 2006-09-24 16:49:18 +0000 |
| commit | 3da41d89a8c827383b2256b965fa1be8b179b9cd (patch) | |
| tree | 04f49d3dab6e586be4769eab29d10618bf8378ea /bin | |
| parent | ad16650e9806bcf864325626da59b93e64ce47ea (diff) | |
| download | mailman-3da41d89a8c827383b2256b965fa1be8b179b9cd.tar.gz mailman-3da41d89a8c827383b2256b965fa1be8b179b9cd.tar.zst mailman-3da41d89a8c827383b2256b965fa1be8b179b9cd.zip | |
Convert check_perms to mmshell symlink, configuration object, and optparse
usage.
Diffstat (limited to 'bin')
| -rw-r--r-- | bin/Makefile.in | 10 | ||||
| -rwxr-xr-x | bin/check_perms | 393 |
2 files changed, 5 insertions, 398 deletions
diff --git a/bin/Makefile.in b/bin/Makefile.in index 37084d1f7..1251cd831 100644 --- a/bin/Makefile.in +++ b/bin/Makefile.in @@ -46,17 +46,17 @@ SHELL= /bin/sh SCRIPTS= mmshell \ remove_members clone_member \ - sync_members check_db withlist check_perms \ + sync_members check_db withlist \ config_list dumpdb cleanarch \ list_admins genaliases \ fix_url.py convert.py transcheck \ msgfmt.py discard \ reset_pw.py templ2pot.py po2templ.py -LN_SCRIPTS= add_members arch change_pw find_member inject list_lists \ - list_members list_owners mailmanctl mmsitepass newlist \ - qrunner rmlist show_qfiles show_mm_cfg testall unshunt \ - update version +LN_SCRIPTS= add_members arch change_pw check_perms find_member inject \ + list_lists list_members list_owners mailmanctl mmsitepass \ + newlist qrunner rmlist show_qfiles show_mm_cfg testall \ + unshunt update version BUILDDIR= ../build/bin diff --git a/bin/check_perms b/bin/check_perms deleted file mode 100755 index 7c807745d..000000000 --- a/bin/check_perms +++ /dev/null @@ -1,393 +0,0 @@ -#! @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 _ - -# 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 _(' 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 _('%(path)s bad group (has: %(groupname)s, ' - 'expected %(MAILMAN_GROUP)s)'), - if STATE.FIX: - print _('(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 _('directory permissions must be %(octperms)s: %(path)s'), - if STATE.FIX: - print _('(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 _('source perms must be %(octperms)s: %(path)s'), - arg.ERRORS += 1 - if STATE.FIX: - print _('(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 _('article db files must be %(octperms)s: %(path)s'), - arg.ERRORS += 1 - if STATE.FIX: - print _('(fixing)') - os.chmod(path, mode | ARTICLEFILEPERMS) - else: - print - -def checkall(): - # first check PREFIX - if STATE.VERBOSE: - prefix = mm_cfg.PREFIX - print _('checking mode for %(prefix)s') - dirs = {} - for d in (mm_cfg.PREFIX, mm_cfg.EXEC_PREFIX, mm_cfg.VAR_PREFIX, - mm_cfg.LOG_DIR): - dirs[d] = True - for d in dirs.keys(): - try: - mode = statmode(d) - except OSError, e: - if e.errno <> errno.ENOENT: raise - print _('WARNING: directory does not exist: %(d)s') - continue - if (mode & DIRPERMS) <> DIRPERMS: - STATE.ERRORS += 1 - print _('directory must be at least 02775: %(d)s'), - if STATE.FIX: - print _('(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 _('checking perms on %(private)s') - # private archives must not be other readable - mode = statmode(private) - if mode & S_IROTH: - STATE.ERRORS += 1 - print _('%(private)s must not be other-readable'), - if STATE.FIX: - print _('(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 _("""\ -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 _('mbox file must be at least 0660:'), mboxfile - if STATE.FIX: - print _('(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 _('%(dbdir)s "other" perms must be 000'), - if STATE.FIX: - print _('(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 _('checking cgi-bin permissions') - exes = os.listdir(cgidir) - for f in exes: - path = os.path.join(cgidir, f) - if STATE.VERBOSE: - print _(' checking set-gid for %(path)s') - mode = statmode(path) - if mode & S_IXGRP and not mode & S_ISGID: - STATE.ERRORS += 1 - print _('%(path)s must be set-gid'), - if STATE.FIX: - print _('(fixing)') - os.chmod(path, mode | S_ISGID) - else: - print - -def checkmail(): - wrapper = os.path.join(mm_cfg.WRAPPER_DIR, 'mailman') - if STATE.VERBOSE: - print _('checking set-gid for %(wrapper)s') - mode = statmode(wrapper) - if not mode & S_ISGID: - STATE.ERRORS += 1 - print _('%(wrapper)s must be set-gid'), - if STATE.FIX: - print _('(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 _('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 _('%(pwfile)s permissions must be exactly 0640 ' - '(got %(octmode)s)'), - if STATE.FIX: - print _('(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 _('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 _(' 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 _('file permissions must be at least 660: %(path)s'), - if STATE.FIX: - print _('(fixing)') - os.chmod(path, mode | targetmode) - else: - print - - - -def usage(code, msg=''): - if code: - fd = sys.stderr - else: - fd = sys.stdout - print >> fd, _(__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 _('No problems found') - else: - print _('Problems found:'), STATE.ERRORS - print _('Re-run as %(MAILMAN_USER)s (or root) with -f flag to fix') |
