diff --git a/FilesCheck.py b/FilesCheck.py index 89d71504..f26fba1f 100644 --- a/FilesCheck.py +++ b/FilesCheck.py @@ -20,29 +20,128 @@ STANDARD_USERS=('root','bin','daemon','adm','lp','sync','shutdown','halt','mail' STANDARD_GROUPS=('root','bin','daemon','sys','adm','tty','disk','lp','mem','kmem','wheel','floppy','mail','news','uucp','man','games','gopher','dip','ftp','smb','cdrom','pppusers','cdwriter','audio','dos','nobody','users','console','utmp','lists','gdm','xfs','popusers','slipusers','slocate', 'x10', 'urpmi', 'apache', 'postgres') +# must be kept in sync with the filesystem package +STANDARD_DIRS=( + '/bin', + '/boot', + '/etc', + '/etc/X11', + '/etc/opt', + '/etc/skel', + '/etc/xinetd.d', + '/home', + '/lib', + '/lib/modules', + '/mnt', + '/mnt/cdrom', + '/mnt/disk', + '/mnt/floppy', + '/opt', + '/proc', + '/root', + '/sbin', + '/tmp', + '/usr', + '/usr/X11R6', + '/usr/X11R6/bin', + '/usr/X11R6/doc', + '/usr/X11R6/include', + '/usr/X11R6/lib', + '/usr/X11R6/man', + '/usr/bin', + '/usr/bin/X11', + '/usr/etc', + '/usr/games', + '/usr/include', + '/usr/lib', + '/usr/lib/X11', + '/usr/lib/games', + '/usr/lib/gcc-lib', + '/usr/local', + '/usr/local/bin', + '/usr/local/doc', + '/usr/local/etc', + '/usr/local/games', + '/usr/local/info', + '/usr/local/lib', + '/usr/local/man', + '/usr/local/man/man1', + '/usr/local/man/man2', + '/usr/local/man/man3', + '/usr/local/man/man4', + '/usr/local/man/man5', + '/usr/local/man/man6', + '/usr/local/man/man7', + '/usr/local/man/man8', + '/usr/local/man/man9', + '/usr/local/man/mann', + '/usr/local/sbin', + '/usr/local/src', + '/usr/sbin', + '/usr/share', + '/usr/share/dict', + '/usr/share/icons', + '/usr/share/doc', + '/usr/share/info', + '/usr/share/man', + '/usr/share/man/man1', + '/usr/share/man/man2', + '/usr/share/man/man3', + '/usr/share/man/man4', + '/usr/share/man/man5', + '/usr/share/man/man6', + '/usr/share/man/man7', + '/usr/share/man/man8', + '/usr/share/man/man9', + '/usr/share/man/mann', + '/usr/share/misc', + '/usr/src', + '/usr/tmp', + '/var', + '/var/cache', + '/var/db', + '/var/lib', + '/var/lib/games', + '/var/lib/misc', + '/var/lib/rpm', + '/var/local', + '/var/lock', + '/var/lock/subsys', + '/var/log', + '/var/mail', + '/var/nis', + '/var/opt', + '/var/preserve', + '/var/run', + '/var/spool', + '/var/spool/mail', + '/var/tmp' + ) + +tmp_regex=re.compile("^/tmp/|^(/var|/usr)/tmp/") +mnt_regex=re.compile("^/mnt/") +opt_regex=re.compile("^/opt/") +home_regex=re.compile("^/home/") +etc_regex=re.compile("^/etc/") +sub_bin_regex=re.compile("^(/usr)?/s?bin/\S+/") +backup_regex=re.compile("~$|\#[^/]+\#$") +compr_regex=re.compile("\.(gz|z|Z|zip|bz2)$") +absolute_regex=re.compile("^/([^/]+)") +absolute2_regex=re.compile("^/?([^/]+)") +points_regex=re.compile("^../(.*)") +doc_regex=re.compile("^/usr/(doc|man|info)|^/usr/share/(doc|man|info)") +bin_regex=re.compile("^(/usr)?/s?bin/") +includefile_regex=re.compile("\.h$|\.a$") +sofile_regex=re.compile("\.so$") +devel_regex=re.compile("-(devel|source)$") +lib_regex=re.compile("lib/lib[^/]*\.so\..*") +ldconfig_regex=re.compile("^[^#]*ldconfig", re.MULTILINE) +info_regex=re.compile("^/usr/share/info") +install_info_regex=re.compile("^[^#]*install-info", re.MULTILINE) +perl_temp_file=re.compile(".*perl.*(bs|\.packlist)$") +cvs_regex=re.compile("/CVS/[^/]+$") + class FilesCheck(AbstractCheck.AbstractCheck): - tmp_regex=re.compile("^/tmp/|^(/var|/usr)/tmp/") - mnt_regex=re.compile("^/mnt/") - opt_regex=re.compile("^/opt/") - home_regex=re.compile("^/home/") - etc_regex=re.compile("^/etc/") - sub_bin_regex=re.compile("^(/usr)?/s?bin/\S+/") - backup_regex=re.compile("~$|\#[^/]+\#$") - compr_regex=re.compile("\.(gz|z|Z|zip|bz2)$") - absolute_regex=re.compile("^/([^/]+)") - absolute2_regex=re.compile("^/?([^/]+)") - points_regex=re.compile("^../(.*)") - doc_regex=re.compile("^/usr/(doc|man|info)|^/usr/share/(doc|man|info)") - bin_regex=re.compile("^(/usr)?/s?bin/") - includefile_regex=re.compile("\.h$|\.a$") - sofile_regex=re.compile("\.so$") - devel_regex=re.compile("-(devel|source)$") - lib_regex=re.compile("lib/lib[^/]*\.so\..*") - ldconfig_regex=re.compile("^[^#]*ldconfig", re.MULTILINE) - info_regex=re.compile("^/usr/share/info") - install_info_regex=re.compile("^[^#]*install-info", re.MULTILINE) - perl_temp_file=re.compile(".*perl.*(bs|\.packlist)$") - cvs_regex=re.compile("/CVS/[^/]+$") def __init__(self): AbstractCheck.AbstractCheck.__init__(self, "FilesCheck") @@ -53,7 +152,7 @@ class FilesCheck(AbstractCheck.AbstractCheck): return # Check if the package is a development package - devel_pkg=FilesCheck.devel_regex.search(pkg.name) + devel_pkg=devel_regex.search(pkg.name) files=pkg.files() config_files=pkg.configFiles() @@ -69,7 +168,7 @@ class FilesCheck(AbstractCheck.AbstractCheck): user=enreg[1] group=enreg[2] - if stat.S_ISREG(mode) and FilesCheck.doc_regex.search(f) and not f in doc_files: + if stat.S_ISREG(mode) and doc_regex.search(f) and not f in doc_files: printError(pkg, "not-listed-as-documentation", f) if not user in STANDARD_USERS: @@ -79,28 +178,28 @@ class FilesCheck(AbstractCheck.AbstractCheck): if stat.S_ISREG(mode): # check ldconfig call in %post and %postun - if FilesCheck.lib_regex.search(f): + if lib_regex.search(f): postin=pkg[rpm.RPMTAG_POSTIN] or pkg[rpm.RPMTAG_POSTINPROG] if not postin: printError(pkg, "library-without-ldconfig-postin", f) else: - if not FilesCheck.ldconfig_regex.search(postin): + if not ldconfig_regex.search(postin): printError(pkg, "postin-without-ldconfig", f) postun=pkg[rpm.RPMTAG_POSTUN] or pkg[rpm.RPMTAG_POSTUNPROG] if not postun: printError(pkg, "library-without-ldconfig-postun", f) else: - if not FilesCheck.ldconfig_regex.search(postun): + if not ldconfig_regex.search(postun): printError(pkg, "postun-without-ldconfig", f) # check install-info call in %post and %postun - if FilesCheck.info_regex.search(f): + if info_regex.search(f): postin=pkg[rpm.RPMTAG_POSTIN] if not postin: printError(pkg, "info-files-without-install-info-postin", f) else: - if not FilesCheck.install_info_regex.search(postin): + if not install_info_regex.search(postin): printError(pkg, "postin-without-install-info", f) postun=pkg[rpm.RPMTAG_POSTUN] @@ -108,37 +207,37 @@ class FilesCheck(AbstractCheck.AbstractCheck): if not postun and not preun: printError(pkg, "info-files-without-install-info-postun", f) else: - if (not postun or not FilesCheck.install_info_regex.search(postun)) and \ - (not preun or not FilesCheck.install_info_regex.search(preun)): + if (not postun or not install_info_regex.search(postun)) and \ + (not preun or not install_info_regex.search(preun)): printError(pkg, "postin-without-install-info", f) # check perl temp file - if FilesCheck.perl_temp_file.search(f): + if perl_temp_file.search(f): printWarning(pkg, 'perl-temp-file', f) - if FilesCheck.tmp_regex.search(f): + if tmp_regex.search(f): printError(pkg, "dir-or-file-in-tmp", f) - elif FilesCheck.mnt_regex.search(f): + elif mnt_regex.search(f): printError(pkg, "dir-or-file-in-mnt", f) - elif FilesCheck.opt_regex.search(f): + elif opt_regex.search(f): printError(pkg, "dir-or-file-in-opt", f) - elif FilesCheck.sub_bin_regex.search(f): + elif sub_bin_regex.search(f): printError(pkg, "subdir-in-bin", f) - elif FilesCheck.backup_regex.search(f): + elif backup_regex.search(f): printError(pkg, "backup-file-in-package", f) - elif FilesCheck.home_regex.search(f): + elif home_regex.search(f): printError(pkg, "dir-or-file-in-home", f) - elif FilesCheck.cvs_regex.search(f): + elif cvs_regex.search(f): printError(pkg, "cvs-internal-file", f) elif f == "/usr/info/dir" or f == "/usr/share/info/dir": printError(pkg, "info-dir-file", f) - if FilesCheck.etc_regex.search(f) and stat.S_ISREG(mode): + if etc_regex.search(f) and stat.S_ISREG(mode): if not f in config_files and not f in ghost_files: printWarning(pkg, "non-conffile-in-etc", f) link=enreg[3] if link != '': - ext=FilesCheck.compr_regex.search(link) + ext=compr_regex.search(link) if ext: if not re.compile("\." + ext.group(1) + "$").search(f): printError(pkg, "compressed-symlink-with-wrong-ext", f, link) @@ -168,9 +267,9 @@ class FilesCheck(AbstractCheck.AbstractCheck): # normal file check if stat.S_ISREG(mode): - if FilesCheck.bin_regex.search(f) and mode & 0111 == 0: + if bin_regex.search(f) and mode & 0111 == 0: printWarning(pkg, "non-executable-in-bin", f, oct(perm)) - if not devel_pkg and FilesCheck.includefile_regex.search(f): + if not devel_pkg and includefile_regex.search(f): printWarning(pkg, "devel-file-in-non-devel-package", f) # normal executable check @@ -182,15 +281,14 @@ class FilesCheck(AbstractCheck.AbstractCheck): elif stat.S_ISDIR(mode): if perm != 0755: printError(pkg, "non-standard-dir-perm", f, oct(perm)) -# for file in files.keys(): -# if f != file and string.find(file, f, 0) != -1: -# printInfo(pkg, "non-empty-dir-listed", f) -# break + if pkg[rpm.RPMTAG_NAME] != 'filesystem': + if f in STANDARD_DIRS: + printError(pkg, "standard-dir-owned-by-package", f) # symbolic link check elif stat.S_ISLNK(mode): - r=FilesCheck.absolute_regex.search(link) - is_so=FilesCheck.sofile_regex.search(f) + r=absolute_regex.search(link) + is_so=sofile_regex.search(f) if not devel_pkg and is_so: printWarning(pkg, "devel-file-in-non-devel-package", f) # absolute link @@ -198,7 +296,7 @@ class FilesCheck(AbstractCheck.AbstractCheck): if not is_so and link not in files.keys(): printWarning(pkg, "dangling-symlink", f, link) linktop=r.group(1) - r=FilesCheck.absolute_regex.search(f) + r=absolute_regex.search(f) if r: filetop=r.group(1) if filetop == linktop: @@ -212,7 +310,7 @@ class FilesCheck(AbstractCheck.AbstractCheck): if not os.path.exists(file): printWarning(pkg, "dangling-symlink", f, link) pathcomponents=string.split(f, '/')[1:] - r=FilesCheck.points_regex.search(link) + r=points_regex.search(link) lastpop=None mylink=None @@ -224,10 +322,10 @@ class FilesCheck(AbstractCheck.AbstractCheck): else: lastpop=pathcomponents[0] pathcomponents=pathcomponents[1:] - r=FilesCheck.points_regex.search(mylink) + r=points_regex.search(mylink) if mylink and lastpop: - r=FilesCheck.absolute2_regex.search(mylink) + r=absolute2_regex.search(mylink) linktop=r.group(1) # does the link go up and then down into the same directory?