diff --git a/CheckSUIDPermissions.py b/CheckSUIDPermissions.py new file mode 100644 index 0000000..ba68b7c --- /dev/null +++ b/CheckSUIDPermissions.py @@ -0,0 +1,169 @@ +# vim:sw=4:et +############################################################################# +# File : CheckSUIDPermissions.py +# Package : rpmlint +# Author : Ludwig Nussel +# Purpose : Check for /etc/permissions violations +############################################################################# + +from Filter import * +import AbstractCheck +import re +import os +import string + +_permissions_d_whitelist = ( +"lprng", +"lprng.paranoid", +"mail-server", +"mail-server.paranoid", +"postfix", +"postfix.paranoid", +"sendmail", +"sendmail.paranoid", +"squid", +"texlive", +"texlive.paranoid", +) + +class SUIDCheck(AbstractCheck.AbstractCheck): + def __init__(self): + AbstractCheck.AbstractCheck.__init__(self, "CheckSUIDPermissions") + self.perms = {} + files = [ "/etc/permissions", "/etc/permissions.secure" ] + + for file in files: + if os.path.exists(file): + self._parsefile(file) + + def _parsefile(self,file): + for line in open(file): + line = line.split('#')[0].split('\n')[0] + if len(line): + line = re.split(r'\s+', line) + fn = line[0] + owner = line[1].replace('.', ':') + mode = line[2] + + self.perms[fn] = { "owner" : owner, "mode" : int(mode,8)&07777} + + def check(self, pkg): + global _permissions_d_whitelist + + if pkg.isSource(): + return + + files = pkg.files() + + permfiles = {} + # first pass, find and parse permissions.d files + for f in files: + if f in pkg.ghostFiles(): + continue + + if f.startswith("/etc/permissions.d/"): + + bn = f[19:] + if not bn in _permissions_d_whitelist: + printError(pkg, "permissions-unauthorized-file", f) + + bn = bn.split('.')[0] + if not bn in permfiles: + permfiles[bn] = 1 + + for f in permfiles: + f = pkg.dirName() + "/etc/permissions.d/" + f + if os.path.exists(f+".secure"): + self._parsefile(f + ".secure") + else: + self._parsefile(f) + + # second pass, find permissions violations + for f in files: + if f in pkg.ghostFiles(): + continue + enreg = files[f] + mode = enreg[0] + owner = enreg[1]+':'+enreg[2] + links = enreg[3] + size = enreg[4] + md5 = enreg[5] + rdev = enreg[7] + +# S_IFSOCK 014 socket +# S_IFLNK 012 symbolic link +# S_IFREG 010 regular file +# S_IFBLK 006 block device +# S_IFDIR 004 directory +# S_IFCHR 002 character device +# S_IFIFO 001 FIFO + type = (mode>>12)&017; + mode &= 07777 + if f in self.perms or (type == 04 and f+"/" in self.perms): + if type == 012: + printWarning(pkg, "permissions-symlink", f) + continue + + m = 0 + o = "invalid" + if type == 04: + if f in self.perms: + printWarning(pkg, 'dir-without-slash', f) + else: + f += '/' + + m = self.perms[f]['mode'] + o = self.perms[f]['owner'] + + if mode != m: + printError(pkg, 'permissions-incorrect', '%(file)s has mode 0%(mode)o but should be 0%(m)o' % \ + { 'file':f, 'mode':mode, 'm':m }) + + if owner != o: + printError(pkg, 'permissions-incorrect-owner', '%(file)s belongs to %(owner)s but should be %(o)s' % \ + { 'file':f, 'owner':owner, 'o':o }) + + elif type != 012: + + if f+'/' in self.perms: + printWarning(pkg, 'permissions-file-as-dir', f+' is a file but listed as directory') + + if mode&06000: + msg = '%(file)s is packaged with setuid/setgid bits (0%(mode)o)' % { 'file':f, 'mode':mode } + if type != 04: + printError(pkg, 'permissions-setuid-bit', msg) + else: + printWarning(pkg, 'permissions-setuid-bit', msg) + + if mode&02: + printError(pkg, 'permissions-world-writable', \ + '%(file)s is packaged with world writable permissions (0%(mode)o)' % \ + { 'file':f, 'mode':mode }) + + +check=SUIDCheck() + +if Config.info: + addDetails( +'permissions-unauthorized-file', +"""Please remove the unauthorized files or contact security@suse.de for review.""", +'permissions-symlink', +"""permissions handling for symlinks is useless. Please contact +security@suse.de to remove the entry.""", +'permissions-dir-without-slash', +"""the entry in the permissions file refers to a directory. Please +contact security@suse.de to append a slash to the entry in order to +avoid security problems.""", +'permissions-file-as-dir', +"""the entry in the permissions file refers to a directory but the +package actually contains a file. Please contact security@suse.de to +remove the slash.""", +'permissions-incorrect', +"""please use the %attr macro to set the correct permissions.""", +'permissions-incorrect-owner', +"""please use the %attr macro to set the correct ownership.""", +'permissions-setuid-bit', +"""Please remove the setuid/setgid bits or contact security@suse.de for review.""", +'permissions-world-writable', +"""Please remove the world writable permissions or contact security@suse.de for review.""" +) diff --git a/config b/config index 5ca4cf5..c7787ed 100644 --- a/config +++ b/config @@ -25,6 +25,7 @@ addCheck("LibraryPolicyCheck") addCheck("CheckIconSizes") #addCheck("CheckStaticLibraries") addCheck("BrandingPolicyCheck") +addCheck("CheckSUIDPermissions") addCheck("CheckKDE4Deps") addCheck("KMPPolicyCheck") diff --git a/config.in b/config.in index c980826..9d10e3b 100644 --- a/config.in +++ b/config.in @@ -25,6 +25,7 @@ addCheck("LibraryPolicyCheck") addCheck("CheckIconSizes") #addCheck("CheckStaticLibraries") addCheck("BrandingPolicyCheck") +addCheck("CheckSUIDPermissions") # stuff autobuild takes care about addFilter(".*invalid-version.*") diff --git a/rpmlint.changes b/rpmlint.changes index 410199a..2bf3957 100644 --- a/rpmlint.changes +++ b/rpmlint.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Tue Oct 28 10:00:09 CET 2008 - lnussel@suse.de + +- add check for /etc/permissions violations + ------------------------------------------------------------------- Wed Sep 3 13:58:22 CEST 2008 - dmueller@suse.de diff --git a/rpmlint.spec b/rpmlint.spec index ba3f31f..e91c312 100644 --- a/rpmlint.spec +++ b/rpmlint.spec @@ -22,7 +22,7 @@ Name: rpmlint BuildRequires: rpm-python Summary: Rpm correctness checker Version: 0.83 -Release: 40 +Release: 42 Source0: %{name}-%{version}.tar.bz2 Source1: config Source1001: config.in @@ -38,6 +38,7 @@ Source10: CheckIconSizes.py Source11: BrandingPolicyCheck.py Source12: CheckKDE4Deps.py Source13: KMPPolicyCheck.py +Source14: CheckSUIDPermissions.py Source100: syntax-validator.py Url: http://rpmlint.zarb.org/ License: GPL v2 or later @@ -190,6 +191,7 @@ cp -p %{SOURCE10} . cp -p %{SOURCE11} . cp -p %{SOURCE12} . cp -p %{SOURCE13} . +cp -p %{SOURCE14} . %build make @@ -216,6 +218,8 @@ rm -rf $RPM_BUILD_ROOT /usr/share/man/man1/rpmlint.1.gz %changelog +* Tue Oct 28 2008 lnussel@suse.de +- add check for /etc/permissions violations * Wed Sep 03 2008 dmueller@suse.de - add description for useless-explicit-requires (bnc#405887) * Thu Aug 21 2008 dmueller@suse.de @@ -250,7 +254,7 @@ rm -rf $RPM_BUILD_ROOT - add a warning for self-conflicts * Thu Jun 05 2008 dmueller@suse.de - fix naming policy check for lib64 based archs (bnc#392524) -* Wed May 14 2008 dmueller@suse.de +* Tue May 13 2008 dmueller@suse.de - fix typo in kde4 deps check * Mon May 05 2008 dmueller@suse.de - fix typo in branding policy check @@ -467,7 +471,7 @@ rm -rf $RPM_BUILD_ROOT - make the buildroot check work - make the buildroot check factor 10-15 faster - fix the pkgconfig check -* Sat Jun 09 2007 dmueller@suse.de +* Fri Jun 08 2007 dmueller@suse.de - fix warning-hide hack (#279865) - description update * Fri Jun 08 2007 dmueller@suse.de