def check_url(self, pkg, tag, url):
        """
        Check that URL points to something that seems to exist.
        Return info() of the response if available.
        """
        if not self.network_enabled:
            if self.verbose:
                printInfo(pkg, 'network-checks-disabled', url)
            return

        if self.verbose:
            printInfo(pkg, 'checking-url', url,
                      '(timeout %s seconds)' % self.network_timeout)

        res = None
        try:
            opener = urllib2.build_opener(_HeadRedirectHandler())
            opener.addheaders = [('User-Agent',
                                  'rpmlint/%s' % Config.__version__)]
            res = opener.open(_HeadRequest(url), timeout=self.network_timeout)
        except Exception as e:
            errstr = str(e) or repr(e) or type(e)
            printWarning(pkg, 'invalid-url', '%s:' % tag, url, errstr)
        info = None
        if res:
            with contextlib.closing(res):
                info = res.info()
        return info
Exemple #2
0
    def check_url(self, pkg, tag, url):
        """
        Check that URL points to something that seems to exist.
        Return info() of the response if available.
        """
        if not self.network_enabled:
            if self.verbose:
                printInfo(pkg, 'network-checks-disabled', url)
            return

        if self.verbose:
            printInfo(pkg, 'checking-url', url,
                      '(timeout %s seconds)' % self.network_timeout)

        res = None
        try:
            opener = urllib2.build_opener(_HeadRedirectHandler())
            opener.addheaders = [('User-Agent',
                                  'rpmlint/%s' % Config.__version__)]
            res = opener.open(_HeadRequest(url), timeout=self.network_timeout)
        except Exception as e:
            errstr = str(e) or repr(e) or type(e)
            printWarning(pkg, 'invalid-url', '%s:' % tag, url, errstr)
        info = None
        if res:
            info = res.info()
            res.close()
        return info
    def check_url(self, pkg, tag, url):
        """Check that URL points to something that seems to exist.
           Return info() of the response if available."""
        if not self.network_enabled:
            if self.verbose:
                printInfo(pkg, 'network-checks-disabled', url)
            return

        if self.verbose:
            printInfo(pkg, 'checking-url', url,
                      '(timeout %s seconds)' % self.network_timeout)

        # Could use timeout kwarg to urlopen, but that's python >= 2.6 only
        socket.setdefaulttimeout(self.network_timeout)
        res = None
        try:
            opener = urllib2.build_opener(_HeadRedirectHandler())
            opener.addheaders = [('User-Agent',
                                  'rpmlint/%s' % Config.__version__)]
            res = opener.open(_HeadRequest(url))
        except Exception:
            e = sys.exc_info()[1]
            errstr = str(e) or repr(e) or type(e)
            printWarning(pkg, 'invalid-url', '%s:' % tag, url, errstr)
        info = None
        if res:
            info = res.info()
            res.close()
        return info
    def check_file(self, pkg, filename):
        pkgfile = pkg.files()[filename]

        if not (stat.S_ISREG(pkgfile.mode) and
                pkgfile.magic.startswith('POSIX shell script')):
            return

        try:
            status, output = Pkg.getstatusoutput(["dash", "-n", filename])
            if status == 2:
                printWarning(pkg, "bin-sh-syntax-error", filename)
            status, output = Pkg.getstatusoutput(
                ["checkbashisms", filename])
            if status == 1:
                printInfo(pkg, "potential-bashisms", filename)
        except (FileNotFoundError, UnicodeDecodeError):
            pass
Exemple #5
0
    def check_url(self, pkg, tag, url):
        """Check that URL points to something that seems to exist.
           Return info() of the response if available."""
        if not self.network_enabled:
            if self.verbose:
                printInfo(pkg, 'network-checks-disabled', url)
            return

        if self.verbose:
            printInfo(pkg, 'checking-url', url,
                      '(timeout %s seconds)' % self.network_timeout)

        # Could use timeout kwarg to urlopen, but that's python >= 2.6 only
        socket.setdefaulttimeout(self.network_timeout)
        res = None
        try:
            opener = urllib2.build_opener(_HeadRedirectHandler())
            opener.addheaders = [('User-Agent',
                                  'rpmlint/%s' % Config.__version__)]
            res = opener.open(_HeadRequest(url))
        except Exception, e:
            errstr = str(e) or repr(e) or type(e)
            printWarning(pkg, 'invalid-url', '%s:' % tag, url, errstr)
Exemple #6
0
    def check_binary(self, pkg):
        files = pkg.files()
        menus = []

        for fname, pkgfile in files.items():
            # Check menu files
            res = menu_file_regex.search(fname)
            mode = pkgfile.mode
            if res:
                basename = res.group(1)
                if not stat.S_ISREG(mode):
                    printError(pkg, 'non-file-in-menu-dir', fname)
                else:
                    if basename != pkg.name:
                        printWarning(pkg, 'non-coherent-menu-filename', fname)
                    if mode & 0o444 != 0o444:
                        printError(pkg, 'non-readable-menu-file', fname)
                    if mode & 0o111:
                        printError(pkg, 'executable-menu-file', fname)
                    menus.append(fname)
            else:
                # Check old menus from KDE and GNOME
                res = old_menu_file_regex.search(fname)
                if res:
                    if stat.S_ISREG(mode):
                        printError(pkg, 'old-menu-entry', fname)
                else:
                    # Check non transparent xpm files
                    res = xpm_ext_regex.search(fname)
                    if res:
                        if stat.S_ISREG(mode) and not pkg.grep(
                                'None",', fname):
                            printWarning(pkg, 'non-transparent-xpm', fname)
                if fname.startswith('/usr/lib64/menu'):
                    printError(pkg, 'menu-in-wrong-dir', fname)

        if menus:
            postin = pkg[rpm.RPMTAG_POSTIN] or \
                pkg.scriptprog(rpm.RPMTAG_POSTINPROG)
            if not postin:
                printError(pkg, 'menu-without-postin')
            elif not update_menus_regex.search(postin):
                printError(pkg, 'postin-without-update-menus')

            postun = pkg[rpm.RPMTAG_POSTUN] or \
                pkg.scriptprog(rpm.RPMTAG_POSTUNPROG)
            if not postun:
                printError(pkg, 'menu-without-postun')
            elif not update_menus_regex.search(postun):
                printError(pkg, 'postun-without-update-menus')

            directory = pkg.dirName()
            for f in menus:
                # remove comments and handle cpp continuation lines
                cmd = Pkg.getstatusoutput(('/lib/cpp', directory + f), True)[1]

                for line in cmd.splitlines():
                    if not line.startswith('?'):
                        continue
                    res = package_regex.search(line)
                    if res:
                        package = res.group(1)
                        if package != pkg.name:
                            printWarning(pkg,
                                         'incoherent-package-value-in-menu',
                                         package, f)
                    else:
                        printInfo(pkg, 'unable-to-parse-menu-entry', line)

                    command = True
                    res = command_regex.search(line)
                    if res:
                        command_line = (res.group(1) or res.group(2)).split()
                        command = command_line[0]
                        for launcher in launchers:
                            if not launcher[0].search(command):
                                continue
                            found = False
                            if launcher[1]:
                                found = '/bin/' + command_line[0] in files or \
                                    '/usr/bin/' + command_line[0] in files or \
                                    '/usr/X11R6/bin/' + command_line[0] \
                                    in files
                                if not found:
                                    for l in launcher[1]:
                                        if l in pkg.req_names():
                                            found = True
                                            break
                                if not found:
                                    printError(
                                        pkg,
                                        'use-of-launcher-in-menu-but-no-requires-on',
                                        launcher[1][0])
                            command = command_line[1]
                            break

                        if command[0] == '/':
                            if command not in files:
                                printWarning(pkg,
                                             'menu-command-not-in-package',
                                             command)
                        elif not ('/bin/' + command in files
                                  or '/usr/bin/' + command in files
                                  or '/usr/X11R6/bin/' + command in files):
                            printWarning(pkg, 'menu-command-not-in-package',
                                         command)
                    else:
                        printWarning(pkg, 'missing-menu-command')
                        command = False

                    res = longtitle_regex.search(line)
                    if res:
                        grp = res.groups()
                        title = grp[1] or grp[2]
                        if title[0] != title[0].upper():
                            printWarning(pkg, 'menu-longtitle-not-capitalized',
                                         title)
                        res = version_regex.search(title)
                        if res:
                            printWarning(pkg, 'version-in-menu-longtitle',
                                         title)
                    else:
                        printError(pkg, 'no-longtitle-in-menu', f)
                        title = None

                    res = title_regex.search(line)
                    if res:
                        grp = res.groups()
                        title = grp[1] or grp[2]
                        if title[0] != title[0].upper():
                            printWarning(pkg, 'menu-title-not-capitalized',
                                         title)
                        res = version_regex.search(title)
                        if res:
                            printWarning(pkg, 'version-in-menu-title', title)
                        if '/' in title:
                            printError(pkg, 'invalid-title', title)
                    else:
                        printError(pkg, 'no-title-in-menu', f)
                        title = None

                    res = needs_regex.search(line)
                    if res:
                        grp = res.groups()
                        needs = (grp[1] or grp[2]).lower()
                        if needs in ('x11', 'text', 'wm'):
                            res = section_regex.search(line)
                            if res:
                                grp = res.groups()
                                section = grp[1] or grp[2]
                                # don't warn entries for sections
                                if command and section not in valid_sections:
                                    printError(pkg, 'invalid-menu-section',
                                               section, f)
                            else:
                                printInfo(pkg, 'unable-to-parse-menu-section',
                                          line)
                        elif needs not in standard_needs:
                            printInfo(pkg, 'strange-needs', needs, f)
                    else:
                        printInfo(pkg, 'unable-to-parse-menu-needs', line)

                    res = icon_regex.search(line)
                    if res:
                        icon = res.group(1)
                        if not icon_ext_regex.search(icon):
                            printWarning(pkg, 'invalid-menu-icon-type', icon)
                        if icon[0] == '/' and needs == 'x11':
                            printWarning(pkg, 'hardcoded-path-in-menu-icon',
                                         icon)
                        else:
                            for path in icon_paths:
                                if (path[0] + icon) not in files:
                                    printError(
                                        pkg, path[1] + '-icon-not-in-package',
                                        icon, f)
                    else:
                        printWarning(pkg, 'no-icon-in-menu', title)

                    res = xdg_migrated_regex.search(line)
                    if res:
                        if not res.group(1).lower() == "true":
                            printError(pkg, 'non-xdg-migrated-menu')
                    else:
                        printError(pkg, 'non-xdg-migrated-menu')
Exemple #7
0
def spell_check(pkg, str, fmt, lang, ignored):

    dict_found = True
    warned = set()
    if enchant:
        if lang == 'C':
            lang = 'en_US'

        checker = _enchant_checkers.get(lang)
        if not checker and lang not in _enchant_checkers:
            try:
                checker = enchant.checker.SpellChecker(
                    lang, filters=[enchant.tokenize.EmailFilter,
                                   enchant.tokenize.URLFilter,
                                   enchant.tokenize.WikiWordFilter])
            except enchant.DictNotFoundError:
                printInfo(pkg, 'enchant-dictionary-not-found', lang)
                pass
            _enchant_checkers[lang] = checker

        if checker:
            # squeeze whitespace to ease leading context check
            checker.set_text(re.sub(r'\s+', ' ', str))
            if use_utf8:
                uppername = Pkg.to_unicode(pkg.header[rpm.RPMTAG_NAME]).upper()
            else:
                uppername = pkg.name.upper()
            upperparts = uppername.split('-')
            if lang.startswith('en'):
                ups = [x + "'S" for x in upperparts]
                upperparts.extend(ups)
            for err in checker:

                # Skip already warned and ignored words
                if err.word in warned or err.word in ignored:
                    continue

                # Skip all capitalized words that do not start a sentence
                if err.word[0].isupper() and not \
                        sentence_break_regex.search(checker.leading_context(3)):
                    continue

                upperword = err.word.upper()

                # Skip all uppercase words
                if err.word == upperword:
                    continue

                # Skip errors containing package name or equal to a
                # "component" of it, case insensitively
                if uppername in upperword or upperword in upperparts:
                    continue

                # Work around enchant's digit tokenizing behavior:
                # http://github.com/rfk/pyenchant/issues/issue/3
                if checker.leading_context(1).isdigit() or \
                        checker.trailing_context(1).isdigit():
                    continue

                # Warn and suggest
                sug = ', '.join(checker.suggest()[:3])
                if sug:
                    sug = '-> %s' % sug
                printWarning(pkg, 'spelling-error', fmt % lang, err.word, sug)
                warned.add(err.word)

        else:
            dict_found = False

    if not enchant or not dict_found:
        for seq in str.split():
            for word in re.split(r'[^a-z]+', seq.lower()):
                if len(word) == 0:
                    continue
                correct = BAD_WORDS.get(word)
                if not correct:
                    continue
                if word[0] == '\'':
                    word = word[1:]
                if word[-1] == '\'':
                    word = word[:-1]
                if word in warned or word in ignored:
                    continue
                printWarning(pkg, 'spelling-error', fmt % lang, word, '->',
                             correct)
                warned.add(word)
Exemple #8
0
    def check_binary(self, pkg):
        files = pkg.files()
        menus = []

        for fname, pkgfile in files.items():
            # Check menu files
            res = menu_file_regex.search(fname)
            mode = pkgfile.mode
            if res:
                basename = res.group(1)
                if not stat.S_ISREG(mode):
                    printError(pkg, 'non-file-in-menu-dir', fname)
                else:
                    if basename != pkg.name:
                        printWarning(pkg, 'non-coherent-menu-filename', fname)
                    if mode & 0o444 != 0o444:
                        printError(pkg, 'non-readable-menu-file', fname)
                    if mode & 0o111:
                        printError(pkg, 'executable-menu-file', fname)
                    menus.append(fname)
            else:
                # Check old menus from KDE and GNOME
                res = old_menu_file_regex.search(fname)
                if res:
                    if stat.S_ISREG(mode):
                        printError(pkg, 'old-menu-entry', fname)
                else:
                    # Check non transparent xpm files
                    res = xpm_ext_regex.search(fname)
                    if res:
                        if stat.S_ISREG(mode) and not pkg.grep('None",', fname):
                            printWarning(pkg, 'non-transparent-xpm', fname)
                if fname.startswith('/usr/lib64/menu'):
                    printError(pkg, 'menu-in-wrong-dir', fname)

        if menus:
            postin = pkg[rpm.RPMTAG_POSTIN] or \
                pkg.scriptprog(rpm.RPMTAG_POSTINPROG)
            if not postin:
                printError(pkg, 'menu-without-postin')
            elif not update_menus_regex.search(postin):
                printError(pkg, 'postin-without-update-menus')

            postun = pkg[rpm.RPMTAG_POSTUN] or \
                pkg.scriptprog(rpm.RPMTAG_POSTUNPROG)
            if not postun:
                printError(pkg, 'menu-without-postun')
            elif not update_menus_regex.search(postun):
                printError(pkg, 'postun-without-update-menus')

            directory = pkg.dirName()
            for f in menus:
                # remove comments and handle cpp continuation lines
                cmd = Pkg.getstatusoutput(('/lib/cpp', directory + f), True)[1]

                for line in cmd.splitlines():
                    if not line.startswith('?'):
                        continue
                    res = package_regex.search(line)
                    if res:
                        package = res.group(1)
                        if package != pkg.name:
                            printWarning(pkg,
                                         'incoherent-package-value-in-menu',
                                         package, f)
                    else:
                        printInfo(pkg, 'unable-to-parse-menu-entry', line)

                    command = True
                    res = command_regex.search(line)
                    if res:
                        command_line = (res.group(1) or res.group(2)).split()
                        command = command_line[0]
                        for launcher in launchers:
                            if not launcher[0].search(command):
                                continue
                            found = False
                            if launcher[1]:
                                found = '/bin/' + command_line[0] in files or \
                                    '/usr/bin/' + command_line[0] in files or \
                                    '/usr/X11R6/bin/' + command_line[0] \
                                    in files
                                if not found:
                                    for l in launcher[1]:
                                        if l in pkg.req_names():
                                            found = True
                                            break
                                if not found:
                                    printError(pkg,
                                               'use-of-launcher-in-menu-but-no-requires-on',
                                               launcher[1][0])
                            command = command_line[1]
                            break

                        if command[0] == '/':
                            if command not in files:
                                printWarning(
                                    pkg, 'menu-command-not-in-package',
                                    command)
                        elif not ('/bin/' + command in files or
                                  '/usr/bin/' + command in files or
                                  '/usr/X11R6/bin/' + command in files):
                            printWarning(pkg, 'menu-command-not-in-package',
                                         command)
                    else:
                        printWarning(pkg, 'missing-menu-command')
                        command = False

                    res = longtitle_regex.search(line)
                    if res:
                        grp = res.groups()
                        title = grp[1] or grp[2]
                        if title[0] != title[0].upper():
                            printWarning(pkg, 'menu-longtitle-not-capitalized',
                                         title)
                        res = version_regex.search(title)
                        if res:
                            printWarning(pkg, 'version-in-menu-longtitle',
                                         title)
                    else:
                        printError(pkg, 'no-longtitle-in-menu', f)
                        title = None

                    res = title_regex.search(line)
                    if res:
                        grp = res.groups()
                        title = grp[1] or grp[2]
                        if title[0] != title[0].upper():
                            printWarning(pkg, 'menu-title-not-capitalized',
                                         title)
                        res = version_regex.search(title)
                        if res:
                            printWarning(pkg, 'version-in-menu-title', title)
                        if '/' in title:
                            printError(pkg, 'invalid-title', title)
                    else:
                        printError(pkg, 'no-title-in-menu', f)
                        title = None

                    res = needs_regex.search(line)
                    if res:
                        grp = res.groups()
                        needs = (grp[1] or grp[2]).lower()
                        if needs in ('x11', 'text', 'wm'):
                            res = section_regex.search(line)
                            if res:
                                grp = res.groups()
                                section = grp[1] or grp[2]
                                # don't warn entries for sections
                                if command and section not in valid_sections:
                                    printError(pkg, 'invalid-menu-section',
                                               section, f)
                            else:
                                printInfo(pkg, 'unable-to-parse-menu-section',
                                          line)
                        elif needs not in standard_needs:
                            printInfo(pkg, 'strange-needs', needs, f)
                    else:
                        printInfo(pkg, 'unable-to-parse-menu-needs', line)

                    res = icon_regex.search(line)
                    if res:
                        icon = res.group(1)
                        if not icon_ext_regex.search(icon):
                            printWarning(pkg, 'invalid-menu-icon-type', icon)
                        if icon[0] == '/' and needs == 'x11':
                            printWarning(pkg, 'hardcoded-path-in-menu-icon',
                                         icon)
                        else:
                            for path in icon_paths:
                                if (path[0] + icon) not in files:
                                    printError(
                                        pkg, path[1] + '-icon-not-in-package',
                                        icon, f)
                    else:
                        printWarning(pkg, 'no-icon-in-menu', title)

                    res = xdg_migrated_regex.search(line)
                    if res:
                        if not res.group(1).lower() == "true":
                            printError(pkg, 'non-xdg-migrated-menu')
                    else:
                        printError(pkg, 'non-xdg-migrated-menu')
    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 bn not in _permissions_d_whitelist:
                    printError(pkg, "permissions-unauthorized-file", f)

                bn = bn.split('.')[0]
                if bn not 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)

        need_set_permissions = False
        found_suseconfig = False
        # second pass, find permissions violations
        for f, pkgfile in files.items():

            if pkgfile.filecaps:
                printError(pkg, 'permissions-fscaps',
                                '%(fname)s has fscaps "%(caps)s"' %
                                {'fname': f, 'caps': pkgfile.filecaps})

            mode = pkgfile.mode
            owner = pkgfile.user + ':' + pkgfile.group

#           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) & 0o17
            mode &= 0o7777
            need_verifyscript = False
            if f in self.perms or (type == 4 and f + "/" in self.perms):
                if type == 0o12:
                    printWarning(pkg, "permissions-symlink", f)
                    continue

                need_verifyscript = True

                m = 0
                o = "invalid"
                if type == 4:
                    if f in self.perms:
                        printWarning(pkg, 'permissions-dir-without-slash', f)
                    else:
                        f += '/'

                if type == 0o10 and mode & 0o111:
                    # pie binaries have 'shared object' here
                    if (pkgfile.magic.startswith('ELF ') and
                            ('shared object' not in pkgfile.magic) and
                            ('pie executable' not in pkgfile.magic)):
                        printError(pkg, 'non-position-independent-executable',
                                   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 != 0o12:

                if f + '/' in self.perms:
                    printWarning(
                        pkg, 'permissions-file-as-dir',
                        f + ' is a file but listed as directory')

                if mode & 0o6000:
                    need_verifyscript = True
                    msg = '%(file)s is packaged with ' \
                          'setuid/setgid bits (0%(mode)o)' % \
                          {'file': f, 'mode': mode}
                    if type != 0o4:
                        printError(pkg, 'permissions-file-setuid-bit', msg)
                    else:
                        printWarning(pkg, 'permissions-directory-setuid-bit', msg)

                    if type == 0o10:
                        if ('shared object' not in pkgfile.magic and
                                'pie executable' not in pkgfile.magic):
                            printError(pkg, 'non-position-independent-executable', f)

                if mode & 0o2:
                    need_verifyscript = True
                    printError(pkg, 'permissions-world-writable',
                               '%(file)s is packaged with world writable permissions (0%(mode)o)' %
                               {'file': f, 'mode': mode})

            script = pkg[rpm.RPMTAG_POSTIN] or pkg.scriptprog(rpm.RPMTAG_POSTINPROG)
            found = False
            if script:
                for line in script.split("\n"):
                    if "chkstat -n" in line and f in line:
                        found = True
                        break

                    if "SuSEconfig --module permissions" in line \
                            or "run_permissions is obsolete" in line:
                        found = True
                        found_suseconfig = True
                        break

            if need_verifyscript and \
                    (f not in self.perms or 'static' not in self.perms[f]):

                if not script or not found:
                    printError(pkg, 'permissions-missing-postin',
                               "missing %%set_permissions %s in %%post" % f)

                need_set_permissions = True
                script = pkg[rpm.RPMTAG_VERIFYSCRIPT] or pkg[rpm.RPMTAG_VERIFYSCRIPTPROG]

                found = False
                if script:
                    for line in script.split("\n"):
                        if "/chkstat" in line and f in line:
                            found = True
                            break

                if not script or not found:
                    printWarning(pkg, 'permissions-missing-verifyscript',
                                 "missing %%verify_permissions -e %s" % f)

        if need_set_permissions:
            if 'permissions' not in map(lambda x: x[0], pkg.prereq()):
                printError(pkg, 'permissions-missing-requires',
                           "missing 'permissions' in PreReq")

        if found_suseconfig:
            printInfo(pkg, 'permissions-suseconfig-obsolete',
                      "%run_permissions is obsolete")
Exemple #10
0
def spell_check(pkg, str, fmt, lang, ignored):

    dict_found = True
    warned = set()
    if enchant:
        if lang == 'C':
            lang = 'en_US'

        checker = _enchant_checkers.get(lang)
        if not checker and lang not in _enchant_checkers:
            try:
                checker = enchant.checker.SpellChecker(
                    lang, filters=[enchant.tokenize.EmailFilter,
                                   enchant.tokenize.URLFilter,
                                   enchant.tokenize.WikiWordFilter])
            except enchant.DictNotFoundError:
                printInfo(pkg, 'enchant-dictionary-not-found', lang)
                pass
            _enchant_checkers[lang] = checker

        if checker:
            # squeeze whitespace to ease leading context check
            checker.set_text(re.sub(r'\s+', ' ', str))
            if use_utf8:
                uppername = Pkg.to_unicode(pkg.header[rpm.RPMTAG_NAME]).upper()
            else:
                uppername = pkg.name.upper()
            upperparts = uppername.split('-')
            if lang.startswith('en'):
                ups = [x + "'S" for x in upperparts]
                upperparts.extend(ups)
            for err in checker:

                # Skip already warned and ignored words
                if err.word in warned or err.word in ignored:
                    continue

                # Skip all capitalized words that do not start a sentence
                if err.word[0].isupper() and not \
                        sentence_break_regex.search(checker.leading_context(3)):
                    continue

                upperword = err.word.upper()

                # Skip all uppercase words
                if err.word == upperword:
                    continue

                # Skip errors containing package name or equal to a
                # "component" of it, case insensitively
                if uppername in upperword or upperword in upperparts:
                    continue

                # Work around enchant's digit tokenizing behavior:
                # http://github.com/rfk/pyenchant/issues/issue/3
                if checker.leading_context(1).isdigit() or \
                        checker.trailing_context(1).isdigit():
                    continue

                # Warn and suggest
                sug = ', '.join(checker.suggest()[:3])
                if sug:
                    sug = '-> %s' % sug
                printWarning(pkg, 'spelling-error', fmt % lang, err.word, sug)
                warned.add(err.word)

        else:
            dict_found = False

    if not enchant or not dict_found:
        for seq in str.split():
            for word in re.split('[^a-z]+', seq.lower()):
                if len(word) == 0:
                    continue
                correct = BAD_WORDS.get(word)
                if not correct:
                    continue
                if word[0] == '\'':
                    word = word[1:]
                if word[-1] == '\'':
                    word = word[:-1]
                if word in warned or word in ignored:
                    continue
                printWarning(pkg, 'spelling-error', fmt % lang, word, '->',
                             correct)
                warned.add(word)
Exemple #11
0
    def check(self, pkg):
        global _permissions_d_whitelist

        if pkg.isSource():
            return

        files = pkg.files()

        permfiles = set()
        # first pass, find and parse permissions.d files
        for f in files:
            for prefix in self._paths_to("permissions.d/"):
                if f.startswith(prefix):

                    if f in pkg.ghostFiles():
                        printError(pkg, 'polkit-ghost-file', f)
                        continue

                    bn = f[len(prefix):]
                    if bn not in _permissions_d_whitelist:
                        printError(pkg, "permissions-unauthorized-file", f)

                    bn = 'permissions.d/' + bn.split('.')[0]
                    if bn not in permfiles:
                        permfiles.add(bn)

        for f in permfiles:
            # check for a .secure file first, falling back to the plain file
            for path in self._paths_to(f + '.secure', f):
                if path in files:
                    self._parseProfile(pkg.dirName() + path)
                    break

        need_set_permissions = False
        found_suseconfig = False
        # second pass, find permissions violations
        for f, pkgfile in files.items():

            if pkgfile.filecaps:
                printError(
                    pkg, 'permissions-fscaps',
                    '%(fname)s has fscaps "%(caps)s"' % {
                        'fname': f,
                        'caps': pkgfile.filecaps
                    })

            mode = pkgfile.mode
            owner = pkgfile.user + ':' + pkgfile.group

            need_verifyscript = False
            if f in self.perms or (stat.S_ISDIR(mode)
                                   and f + "/" in self.perms):
                if stat.S_ISLNK(mode):
                    printWarning(pkg, "permissions-symlink", f)
                    continue

                need_verifyscript = True

                m = 0
                o = "invalid"
                if stat.S_ISDIR(mode):
                    if f in self.perms:
                        printWarning(pkg, 'permissions-dir-without-slash', f)
                    else:
                        f += '/'

                entry = self.perms[f]

                if stat.S_ISREG(mode) and mode & (stat.S_IXUSR | stat.S_IXGRP
                                                  | stat.S_IXOTH):
                    # pie binaries have 'shared object' here
                    if (pkgfile.magic.startswith('ELF ')
                            and ('shared object' not in pkgfile.magic)
                            and ('pie executable' not in pkgfile.magic)):
                        printError(pkg, 'non-position-independent-executable',
                                   f)

                m = entry.mode
                o = ':'.join((entry.owner, entry.group))

                if stat.S_IMODE(mode) != m:
                    printError(
                        pkg, 'permissions-incorrect',
                        '%(file)s has mode 0%(mode)o but should be 0%(m)o' % {
                            'file': f,
                            'mode': stat.S_IMODE(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 not stat.S_ISLNK(mode):

                if f + '/' in self.perms:
                    printWarning(pkg, 'permissions-file-as-dir',
                                 f + ' is a file but listed as directory')

                if mode & (stat.S_ISUID | stat.S_ISGID):
                    need_verifyscript = True
                    msg = '%(file)s is packaged with ' \
                          'setuid/setgid bits (0%(mode)o)' % \
                          {'file': f, 'mode': stat.S_IMODE(mode)}
                    if not stat.S_ISDIR(mode):
                        printError(pkg, 'permissions-file-setuid-bit', msg)
                    else:
                        printWarning(pkg, 'permissions-directory-setuid-bit',
                                     msg)

                    if stat.S_ISREG(mode):
                        if ('shared object' not in pkgfile.magic
                                and 'pie executable' not in pkgfile.magic):
                            printError(pkg,
                                       'non-position-independent-executable',
                                       f)

            script = pkg[rpm.RPMTAG_POSTIN] or pkg.scriptprog(
                rpm.RPMTAG_POSTINPROG)
            found = False
            if script:
                for line in script.split("\n"):
                    if "chkstat -n" in line and f in line:
                        found = True
                        break

                    if "SuSEconfig --module permissions" in line \
                            or "run_permissions is obsolete" in line:
                        found = True
                        found_suseconfig = True
                        break

            if need_verifyscript and \
                    (f not in self.perms or not self._isStaticEntry(self.perms[f])):

                if not script or not found:
                    printError(pkg, 'permissions-missing-postin',
                               "missing %%set_permissions %s in %%post" % f)

                need_set_permissions = True
                script = pkg[rpm.RPMTAG_VERIFYSCRIPT] or pkg[
                    rpm.RPMTAG_VERIFYSCRIPTPROG]

                found = False
                if script:
                    for line in script.split("\n"):
                        if "/chkstat" in line and f in line:
                            found = True
                            break

                if not script or not found:
                    printWarning(pkg, 'permissions-missing-verifyscript',
                                 "missing %%verify_permissions -e %s" % f)

        if need_set_permissions:
            if 'permissions' not in map(lambda x: x[0], pkg.prereq()):
                printError(pkg, 'permissions-missing-requires',
                           "missing 'permissions' in PreReq")

        if found_suseconfig:
            printInfo(pkg, 'permissions-suseconfig-obsolete',
                      "%run_permissions is obsolete")
    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 bn not in _permissions_d_whitelist:
                    printError(pkg, "permissions-unauthorized-file", f)

                bn = bn.split('.')[0]
                if bn not 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)

        need_set_permissions = False
        found_suseconfig = False
        # second pass, find permissions violations
        for f, pkgfile in files.items():

            if pkgfile.filecaps:
                printError(
                    pkg, 'permissions-fscaps',
                    '%(fname)s has fscaps "%(caps)s"' % {
                        'fname': f,
                        'caps': pkgfile.filecaps
                    })

            mode = pkgfile.mode
            owner = pkgfile.user + ':' + pkgfile.group

            #           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) & 0o17
            mode &= 0o7777
            need_verifyscript = False
            if f in self.perms or (type == 4 and f + "/" in self.perms):
                if type == 0o12:
                    printWarning(pkg, "permissions-symlink", f)
                    continue

                need_verifyscript = True

                m = 0
                o = "invalid"
                if type == 4:
                    if f in self.perms:
                        printWarning(pkg, 'permissions-dir-without-slash', f)
                    else:
                        f += '/'

                if type == 0o10 and mode & 0o111:
                    # pie binaries have 'shared object' here
                    if (pkgfile.magic.startswith('ELF ')
                            and ('shared object' not in pkgfile.magic)
                            and ('pie executable' not in pkgfile.magic)):
                        printError(pkg, 'non-position-independent-executable',
                                   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 != 0o12:

                if f + '/' in self.perms:
                    printWarning(pkg, 'permissions-file-as-dir',
                                 f + ' is a file but listed as directory')

                if mode & 0o6000:
                    need_verifyscript = True
                    msg = '%(file)s is packaged with ' \
                          'setuid/setgid bits (0%(mode)o)' % \
                          {'file': f, 'mode': mode}
                    if type != 0o4:
                        printError(pkg, 'permissions-file-setuid-bit', msg)
                    else:
                        printWarning(pkg, 'permissions-directory-setuid-bit',
                                     msg)

                    if type == 0o10:
                        if ('shared object' not in pkgfile.magic
                                and 'pie executable' not in pkgfile.magic):
                            printError(pkg,
                                       'non-position-independent-executable',
                                       f)

                if mode & 0o2:
                    need_verifyscript = True
                    printError(
                        pkg, 'permissions-world-writable',
                        '%(file)s is packaged with world writable permissions (0%(mode)o)'
                        % {
                            'file': f,
                            'mode': mode
                        })

            script = pkg[rpm.RPMTAG_POSTIN] or pkg.scriptprog(
                rpm.RPMTAG_POSTINPROG)
            found = False
            if script:
                for line in script.split("\n"):
                    if "chkstat -n" in line and f in line:
                        found = True
                        break

                    if "SuSEconfig --module permissions" in line \
                            or "run_permissions is obsolete" in line:
                        found = True
                        found_suseconfig = True
                        break

            if need_verifyscript and \
                    (f not in self.perms or 'static' not in self.perms[f]):

                if not script or not found:
                    printError(pkg, 'permissions-missing-postin',
                               "missing %%set_permissions %s in %%post" % f)

                need_set_permissions = True
                script = pkg[rpm.RPMTAG_VERIFYSCRIPT] or pkg[
                    rpm.RPMTAG_VERIFYSCRIPTPROG]

                found = False
                if script:
                    for line in script.split("\n"):
                        if "/chkstat" in line and f in line:
                            found = True
                            break

                if not script or not found:
                    printWarning(pkg, 'permissions-missing-verifyscript',
                                 "missing %%verify_permissions -e %s" % f)

        if need_set_permissions:
            if 'permissions' not in map(lambda x: x[0], pkg.prereq()):
                printError(pkg, 'permissions-missing-requires',
                           "missing 'permissions' in PreReq")

        if found_suseconfig:
            printInfo(pkg, 'permissions-suseconfig-obsolete',
                      "%run_permissions is obsolete")