Blame python/audit2allow/audit2why

Packit Service 9fb14c
#!/usr/bin/python3 -Es
Packit Service 9fb14c
# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
Packit Service 9fb14c
# Authors: Dan Walsh <dwalsh@redhat.com>
Packit Service 9fb14c
#
Packit Service 9fb14c
# Copyright (C) 2006-2013  Red Hat
Packit Service 9fb14c
# see file 'COPYING' for use and warranty information
Packit Service 9fb14c
#
Packit Service 9fb14c
# This program is free software; you can redistribute it and/or
Packit Service 9fb14c
# modify it under the terms of the GNU General Public License as
Packit Service 9fb14c
# published by the Free Software Foundation; version 2 only
Packit Service 9fb14c
#
Packit Service 9fb14c
# This program is distributed in the hope that it will be useful,
Packit Service 9fb14c
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 9fb14c
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 9fb14c
# GNU General Public License for more details.
Packit Service 9fb14c
#
Packit Service 9fb14c
# You should have received a copy of the GNU General Public License
Packit Service 9fb14c
# along with this program; if not, write to the Free Software
Packit Service 9fb14c
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Packit Service 9fb14c
#
Packit Service 9fb14c
Packit Service 9fb14c
import sys
Packit Service 9fb14c
import os
Packit Service 9fb14c
Packit Service 9fb14c
import sepolgen.audit as audit
Packit Service 9fb14c
import sepolgen.policygen as policygen
Packit Service 9fb14c
import sepolgen.interfaces as interfaces
Packit Service 9fb14c
import sepolgen.output as output
Packit Service 9fb14c
import sepolgen.objectmodel as objectmodel
Packit Service 9fb14c
import sepolgen.defaults as defaults
Packit Service 9fb14c
import sepolgen.module as module
Packit Service 9fb14c
from sepolgen.sepolgeni18n import _
Packit Service 9fb14c
import selinux.audit2why as audit2why
Packit Service 9fb14c
import locale
Packit Service 9fb14c
try:
Packit Service 9fb14c
    locale.setlocale(locale.LC_ALL, '')
Packit Service 9fb14c
except:
Packit Service 9fb14c
    pass
Packit Service 9fb14c
Packit Service 9fb14c
Packit Service 9fb14c
class AuditToPolicy:
Packit Service 9fb14c
    VERSION = "%prog .1"
Packit Service 9fb14c
    SYSLOG = "/var/log/messages"
Packit Service 9fb14c
Packit Service 9fb14c
    def __init__(self):
Packit Service 9fb14c
        self.__options = None
Packit Service 9fb14c
        self.__parser = None
Packit Service 9fb14c
        self.__avs = None
Packit Service 9fb14c
Packit Service 9fb14c
    def __parse_options(self):
Packit Service 9fb14c
        from optparse import OptionParser
Packit Service 9fb14c
Packit Service 9fb14c
        parser = OptionParser(version=self.VERSION)
Packit Service 9fb14c
        parser.add_option("-b", "--boot", action="store_true", dest="boot", default=False,
Packit Service 9fb14c
                          help="audit messages since last boot conflicts with -i")
Packit Service 9fb14c
        parser.add_option("-a", "--all", action="store_true", dest="audit", default=False,
Packit Service 9fb14c
                          help="read input from audit log - conflicts with -i")
Packit Service 9fb14c
        parser.add_option("-p", "--policy", dest="policy", default=None, help="Policy file to use for analysis")
Packit Service 9fb14c
        parser.add_option("-d", "--dmesg", action="store_true", dest="dmesg", default=False,
Packit Service 9fb14c
                          help="read input from dmesg - conflicts with --all and --input")
Packit Service 9fb14c
        parser.add_option("-i", "--input", dest="input",
Packit Service 9fb14c
                          help="read input from <input> - conflicts with -a")
Packit Service 9fb14c
        parser.add_option("-l", "--lastreload", action="store_true", dest="lastreload", default=False,
Packit Service 9fb14c
                          help="read input only after the last reload")
Packit Service 9fb14c
        parser.add_option("-r", "--requires", action="store_true", dest="requires", default=False,
Packit Service 9fb14c
                          help="generate require statements for rules")
Packit Service 9fb14c
        parser.add_option("-m", "--module", dest="module",
Packit Service 9fb14c
                          help="set the module name - implies --requires")
Packit Service 9fb14c
        parser.add_option("-M", "--module-package", dest="module_package",
Packit Service 9fb14c
                          help="generate a module package - conflicts with -o and -m")
Packit Service 9fb14c
        parser.add_option("-o", "--output", dest="output",
Packit Service 9fb14c
                          help="append output to <filename>, conflicts with -M")
Packit Service 9fb14c
        parser.add_option("-D", "--dontaudit", action="store_true",
Packit Service 9fb14c
                          dest="dontaudit", default=False,
Packit Service 9fb14c
                          help="generate policy with dontaudit rules")
Packit Service 9fb14c
        parser.add_option("-R", "--reference", action="store_true", dest="refpolicy",
Packit Service 9fb14c
                          default=True, help="generate refpolicy style output")
Packit Service 9fb14c
Packit Service 9fb14c
        parser.add_option("-N", "--noreference", action="store_false", dest="refpolicy",
Packit Service 9fb14c
                          default=False, help="do not generate refpolicy style output")
Packit Service 9fb14c
        parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
Packit Service 9fb14c
                          default=False, help="explain generated output")
Packit Service 9fb14c
        parser.add_option("-e", "--explain", action="store_true", dest="explain_long",
Packit Service 9fb14c
                          default=False, help="fully explain generated output")
Packit Service 9fb14c
        parser.add_option("-t", "--type", help="only process messages with a type that matches this regex",
Packit Service 9fb14c
                          dest="type")
Packit Service 9fb14c
        parser.add_option("--perm-map", dest="perm_map", help="file name of perm map")
Packit Service 9fb14c
        parser.add_option("--interface-info", dest="interface_info", help="file name of interface information")
Packit Service 9fb14c
        parser.add_option("-x", "--xperms", action="store_true", dest="xperms",
Packit Service 9fb14c
                          default=False, help="generate extended permission rules")
Packit Service 9fb14c
        parser.add_option("--debug", dest="debug", action="store_true", default=False,
Packit Service 9fb14c
                          help="leave generated modules for -M")
Packit Service 9fb14c
        parser.add_option("-w", "--why", dest="audit2why", action="store_true", default=(os.path.basename(sys.argv[0]) == "audit2why"),
Packit Service 9fb14c
                          help="Translates SELinux audit messages into a description of why the access was denied")
Packit Service 9fb14c
Packit Service 9fb14c
        options, args = parser.parse_args()
Packit Service 9fb14c
Packit Service 9fb14c
        # Make -d, -a, and -i conflict
Packit Service 9fb14c
        if options.audit is True or options.boot:
Packit Service 9fb14c
            if options.input is not None:
Packit Service 9fb14c
                sys.stderr.write("error: --all/--boot conflicts with --input\n")
Packit Service 9fb14c
            if options.dmesg is True:
Packit Service 9fb14c
                sys.stderr.write("error: --all/--boot conflicts with --dmesg\n")
Packit Service 9fb14c
        if options.input is not None and options.dmesg is True:
Packit Service 9fb14c
            sys.stderr.write("error: --input conflicts with --dmesg\n")
Packit Service 9fb14c
Packit Service 9fb14c
        # Turn on requires generation if a module name is given. Also verify
Packit Service 9fb14c
        # the module name.
Packit Service 9fb14c
        if options.module:
Packit Service 9fb14c
            name = options.module
Packit Service 9fb14c
        else:
Packit Service 9fb14c
            name = options.module_package
Packit Service 9fb14c
        if name:
Packit Service 9fb14c
            options.requires = True
Packit Service 9fb14c
            if not module.is_valid_name(name):
Packit Service 9fb14c
                sys.stderr.write('error: module names must begin with a letter, optionally followed by letters, numbers, "-", "_", "."\n')
Packit Service 9fb14c
                sys.exit(2)
Packit Service 9fb14c
Packit Service 9fb14c
        # Make -M and -o conflict
Packit Service 9fb14c
        if options.module_package:
Packit Service 9fb14c
            if options.output:
Packit Service 9fb14c
                sys.stderr.write("error: --module-package conflicts with --output\n")
Packit Service 9fb14c
                sys.exit(2)
Packit Service 9fb14c
            if options.module:
Packit Service 9fb14c
                sys.stderr.write("error: --module-package conflicts with --module\n")
Packit Service 9fb14c
                sys.exit(2)
Packit Service 9fb14c
Packit Service 9fb14c
        self.__options = options
Packit Service 9fb14c
Packit Service 9fb14c
    def __read_input(self):
Packit Service 9fb14c
        parser = audit.AuditParser(last_load_only=self.__options.lastreload)
Packit Service 9fb14c
Packit Service 9fb14c
        filename = None
Packit Service 9fb14c
        messages = None
Packit Service 9fb14c
        f = None
Packit Service 9fb14c
Packit Service 9fb14c
        # Figure out what input we want
Packit Service 9fb14c
        if self.__options.input is not None:
Packit Service 9fb14c
            filename = self.__options.input
Packit Service 9fb14c
        elif self.__options.dmesg:
Packit Service 9fb14c
            messages = audit.get_dmesg_msgs()
Packit Service 9fb14c
        elif self.__options.audit:
Packit Service 9fb14c
            try:
Packit Service 9fb14c
                messages = audit.get_audit_msgs()
Packit Service 9fb14c
            except OSError as e:
Packit Service 9fb14c
                sys.stderr.write('could not run ausearch - "%s"\n' % str(e))
Packit Service 9fb14c
                sys.exit(1)
Packit Service 9fb14c
        elif self.__options.boot:
Packit Service 9fb14c
            try:
Packit Service 9fb14c
                messages = audit.get_audit_boot_msgs()
Packit Service 9fb14c
            except OSError as e:
Packit Service 9fb14c
                sys.stderr.write('could not run ausearch - "%s"\n' % str(e))
Packit Service 9fb14c
                sys.exit(1)
Packit Service 9fb14c
        else:
Packit Service 9fb14c
            # This is the default if no input is specified
Packit Service 9fb14c
            f = sys.stdin
Packit Service 9fb14c
Packit Service 9fb14c
        # Get the input
Packit Service 9fb14c
        if filename is not None:
Packit Service 9fb14c
            try:
Packit Service 9fb14c
                f = open(filename)
Packit Service 9fb14c
            except IOError as e:
Packit Service 9fb14c
                sys.stderr.write('could not open file %s - "%s"\n' % (filename, str(e)))
Packit Service 9fb14c
                sys.exit(1)
Packit Service 9fb14c
Packit Service 9fb14c
        if f is not None:
Packit Service 9fb14c
            parser.parse_file(f)
Packit Service 9fb14c
            f.close()
Packit Service 9fb14c
Packit Service 9fb14c
        if messages is not None:
Packit Service 9fb14c
            parser.parse_string(messages)
Packit Service 9fb14c
Packit Service 9fb14c
        self.__parser = parser
Packit Service 9fb14c
Packit Service 9fb14c
    def __process_input(self):
Packit Service 9fb14c
        if self.__options.type:
Packit Service 9fb14c
            avcfilter = audit.AVCTypeFilter(self.__options.type)
Packit Service 9fb14c
            self.__avs = self.__parser.to_access(avcfilter)
Packit Service 9fb14c
            csfilter = audit.ComputeSidTypeFilter(self.__options.type)
Packit Service 9fb14c
            self.__role_types = self.__parser.to_role(csfilter)
Packit Service 9fb14c
        else:
Packit Service 9fb14c
            self.__avs = self.__parser.to_access()
Packit Service 9fb14c
            self.__role_types = self.__parser.to_role()
Packit Service 9fb14c
Packit Service 9fb14c
    def __load_interface_info(self):
Packit Service 9fb14c
        # Load interface info file
Packit Service 9fb14c
        if self.__options.interface_info:
Packit Service 9fb14c
            fn = self.__options.interface_info
Packit Service 9fb14c
        else:
Packit Service 9fb14c
            fn = defaults.interface_info()
Packit Service 9fb14c
        try:
Packit Service 9fb14c
            fd = open(fn)
Packit Service 9fb14c
        except:
Packit Service 9fb14c
            sys.stderr.write("could not open interface info [%s]\n" % fn)
Packit Service 9fb14c
            sys.exit(1)
Packit Service 9fb14c
Packit Service 9fb14c
        ifs = interfaces.InterfaceSet()
Packit Service 9fb14c
        ifs.from_file(fd)
Packit Service 9fb14c
        fd.close()
Packit Service 9fb14c
Packit Service 9fb14c
        # Also load perm maps
Packit Service 9fb14c
        if self.__options.perm_map:
Packit Service 9fb14c
            fn = self.__options.perm_map
Packit Service 9fb14c
        else:
Packit Service 9fb14c
            fn = defaults.perm_map()
Packit Service 9fb14c
        try:
Packit Service 9fb14c
            fd = open(fn)
Packit Service 9fb14c
        except:
Packit Service 9fb14c
            sys.stderr.write("could not open perm map [%s]\n" % fn)
Packit Service 9fb14c
            sys.exit(1)
Packit Service 9fb14c
Packit Service 9fb14c
        perm_maps = objectmodel.PermMappings()
Packit Service 9fb14c
        perm_maps.from_file(fd)
Packit Service 9fb14c
Packit Service 9fb14c
        return (ifs, perm_maps)
Packit Service 9fb14c
Packit Service 9fb14c
    def __output_modulepackage(self, writer, generator):
Packit Service 9fb14c
        generator.set_module_name(self.__options.module_package)
Packit Service 9fb14c
        filename = self.__options.module_package + ".te"
Packit Service 9fb14c
        packagename = self.__options.module_package + ".pp"
Packit Service 9fb14c
Packit Service 9fb14c
        try:
Packit Service 9fb14c
            fd = open(filename, "w")
Packit Service 9fb14c
        except IOError as e:
Packit Service 9fb14c
            sys.stderr.write("could not write output file: %s\n" % str(e))
Packit Service 9fb14c
            sys.exit(1)
Packit Service 9fb14c
Packit Service 9fb14c
        writer.write(generator.get_module(), fd)
Packit Service 9fb14c
        fd.close()
Packit Service 9fb14c
Packit Service 9fb14c
        mc = module.ModuleCompiler()
Packit Service 9fb14c
Packit Service 9fb14c
        try:
Packit Service 9fb14c
            mc.create_module_package(filename, self.__options.refpolicy)
Packit Service 9fb14c
        except RuntimeError as e:
Packit Service 9fb14c
            print(e)
Packit Service 9fb14c
            sys.exit(1)
Packit Service 9fb14c
Packit Service 9fb14c
        sys.stdout.write(_("******************** IMPORTANT ***********************\n"))
Packit Service 9fb14c
        sys.stdout.write((_("To make this policy package active, execute:" +
Packit Service 9fb14c
                            "\n\nsemodule -i %s\n\n") % packagename))
Packit Service 9fb14c
Packit Service 9fb14c
    def __output_audit2why(self):
Packit Service 9fb14c
        import selinux
Packit Service 9fb14c
        try:
Packit Service 9fb14c
            import sepolicy
Packit Service 9fb14c
        except (ImportError, ValueError):
Packit Service 9fb14c
            sepolicy = None
Packit Service 9fb14c
        for i in self.__parser.avc_msgs:
Packit Service 9fb14c
            rc = i.type
Packit Service 9fb14c
            data = i.data
Packit Service 9fb14c
            if rc >= 0:
Packit Service 9fb14c
                print("%s\n\tWas caused by:" % i.message)
Packit Service 9fb14c
            if rc == audit2why.ALLOW:
Packit Service 9fb14c
                print("\t\tUnknown - would be allowed by active policy")
Packit Service 9fb14c
                print("\t\tPossible mismatch between this policy and the one under which the audit message was generated.\n")
Packit Service 9fb14c
                print("\t\tPossible mismatch between current in-memory boolean settings vs. permanent ones.\n")
Packit Service 9fb14c
                continue
Packit Service 9fb14c
            if rc == audit2why.DONTAUDIT:
Packit Service 9fb14c
                print("\t\tUnknown - should be dontaudit'd by active policy")
Packit Service 9fb14c
                print("\t\tPossible mismatch between this policy and the one under which the audit message was generated.\n")
Packit Service 9fb14c
                print("\t\tPossible mismatch between current in-memory boolean settings vs. permanent ones.\n")
Packit Service 9fb14c
                continue
Packit Service 9fb14c
            if rc == audit2why.BOOLEAN:
Packit Service 9fb14c
                if len(data) > 1:
Packit Service 9fb14c
                    print("\tOne of the following booleans was set incorrectly.")
Packit Service 9fb14c
                    for b in data:
Packit Service 9fb14c
                        if sepolicy is not None:
Packit Service 9fb14c
                            print("\tDescription:\n\t%s\n" % sepolicy.boolean_desc(b[0]))
Packit Service 9fb14c
                        print("\tAllow access by executing:\n\t# setsebool -P %s %d" % (b[0], b[1]))
Packit Service 9fb14c
                else:
Packit Service 9fb14c
                    print("\tThe boolean %s was set incorrectly. " % (data[0][0]))
Packit Service 9fb14c
                    if sepolicy is not None:
Packit Service 9fb14c
                        print("\tDescription:\n\t%s\n" % sepolicy.boolean_desc(data[0][0]))
Packit Service 9fb14c
                    print("\tAllow access by executing:\n\t# setsebool -P %s %d" % (data[0][0], data[0][1]))
Packit Service 9fb14c
                continue
Packit Service 9fb14c
Packit Service 9fb14c
            if rc == audit2why.TERULE:
Packit Service 9fb14c
                print("\t\tMissing type enforcement (TE) allow rule.\n")
Packit Service 9fb14c
                print("\t\tYou can use audit2allow to generate a loadable module to allow this access.\n")
Packit Service 9fb14c
                continue
Packit Service 9fb14c
Packit Service 9fb14c
            if rc == audit2why.CONSTRAINT:
Packit Service 9fb14c
                print()  # !!!! This avc is a constraint violation.  You would need to modify the attributes of either the source or target types to allow this access.\n"
Packit Service 9fb14c
                print("#Constraint rule:")
Packit Service 9fb14c
                print("\n#\t" + data[0])
Packit Service 9fb14c
                for reason in data[1:]:
Packit Service 9fb14c
                    print("#\tPossible cause is the source %s and target %s are different.\n" % reason)
Packit Service 9fb14c
Packit Service 9fb14c
            if rc == audit2why.RBAC:
Packit Service 9fb14c
                print("\t\tMissing role allow rule.\n")
Packit Service 9fb14c
                print("\t\tAdd an allow rule for the role pair.\n")
Packit Service 9fb14c
                continue
Packit Service 9fb14c
Packit Service 9fb14c
            if rc == audit2why.BOUNDS:
Packit Service 9fb14c
                print("\t\tTypebounds violation.\n")
Packit Service 9fb14c
                print("\t\tAdd an allow rule for the parent type.\n")
Packit Service 9fb14c
                continue
Packit Service 9fb14c
Packit Service 9fb14c
        audit2why.finish()
Packit Service 9fb14c
        return
Packit Service 9fb14c
Packit Service 9fb14c
    def __output(self):
Packit Service 9fb14c
Packit Service 9fb14c
        if self.__options.audit2why:
Packit Service 9fb14c
            try:
Packit Service 9fb14c
                return self.__output_audit2why()
Packit Service 9fb14c
            except RuntimeError as e:
Packit Service 9fb14c
                print(e)
Packit Service 9fb14c
                sys.exit(1)
Packit Service 9fb14c
Packit Service 9fb14c
        g = policygen.PolicyGenerator()
Packit Service 9fb14c
Packit Service 9fb14c
        g.set_gen_dontaudit(self.__options.dontaudit)
Packit Service 9fb14c
Packit Service 9fb14c
        if self.__options.module:
Packit Service 9fb14c
            g.set_module_name(self.__options.module)
Packit Service 9fb14c
Packit Service 9fb14c
        # Interface generation
Packit Service 9fb14c
        if self.__options.refpolicy:
Packit Service 9fb14c
            ifs, perm_maps = self.__load_interface_info()
Packit Service 9fb14c
            g.set_gen_refpol(ifs, perm_maps)
Packit Service 9fb14c
Packit Service 9fb14c
        # Extended permissions
Packit Service 9fb14c
        if self.__options.xperms:
Packit Service 9fb14c
            g.set_gen_xperms(True)
Packit Service 9fb14c
Packit Service 9fb14c
        # Explanation
Packit Service 9fb14c
        if self.__options.verbose:
Packit Service 9fb14c
            g.set_gen_explain(policygen.SHORT_EXPLANATION)
Packit Service 9fb14c
        if self.__options.explain_long:
Packit Service 9fb14c
            g.set_gen_explain(policygen.LONG_EXPLANATION)
Packit Service 9fb14c
Packit Service 9fb14c
        # Requires
Packit Service 9fb14c
        if self.__options.requires:
Packit Service 9fb14c
            g.set_gen_requires(True)
Packit Service 9fb14c
Packit Service 9fb14c
        # Generate the policy
Packit Service 9fb14c
        g.add_access(self.__avs)
Packit Service 9fb14c
        g.add_role_types(self.__role_types)
Packit Service 9fb14c
Packit Service 9fb14c
        # Output
Packit Service 9fb14c
        writer = output.ModuleWriter()
Packit Service 9fb14c
Packit Service 9fb14c
        # Module package
Packit Service 9fb14c
        if self.__options.module_package:
Packit Service 9fb14c
            self.__output_modulepackage(writer, g)
Packit Service 9fb14c
        else:
Packit Service 9fb14c
            # File or stdout
Packit Service 9fb14c
            if self.__options.module:
Packit Service 9fb14c
                g.set_module_name(self.__options.module)
Packit Service 9fb14c
Packit Service 9fb14c
            if self.__options.output:
Packit Service 9fb14c
                fd = open(self.__options.output, "a")
Packit Service 9fb14c
            else:
Packit Service 9fb14c
                fd = sys.stdout
Packit Service 9fb14c
            writer.write(g.get_module(), fd)
Packit Service 9fb14c
Packit Service 9fb14c
    def main(self):
Packit Service 9fb14c
        try:
Packit Service 9fb14c
            self.__parse_options()
Packit Service 9fb14c
            if self.__options.policy:
Packit Service 9fb14c
                audit2why.init(self.__options.policy)
Packit Service 9fb14c
            else:
Packit Service 9fb14c
                audit2why.init()
Packit Service 9fb14c
Packit Service 9fb14c
            self.__read_input()
Packit Service 9fb14c
            self.__process_input()
Packit Service 9fb14c
            self.__output()
Packit Service 9fb14c
        except KeyboardInterrupt:
Packit Service 9fb14c
            sys.exit(0)
Packit Service 9fb14c
        except ValueError as e:
Packit Service 9fb14c
            print(e)
Packit Service 9fb14c
            sys.exit(1)
Packit Service 9fb14c
        except IOError as e:
Packit Service 9fb14c
            print(e)
Packit Service 9fb14c
            sys.exit(1)
Packit Service 9fb14c
Packit Service 9fb14c
if __name__ == "__main__":
Packit Service 9fb14c
    app = AuditToPolicy()
Packit Service 9fb14c
    app.main()