# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
#
# Copyright (C) 2006 Red Hat
# see file 'COPYING' for use and warranty information
#
# 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; version 2 only
#
# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#

"""
classes and algorithms for the generation of SELinux policy.
"""

import itertools
import textwrap

import refpolicy
import objectmodel
import access
import interfaces
import matching
import selinux.audit2why as audit2why
try:
    from setools import *
except:
    pass

# Constants for the level of explanation from the generation
# routines
NO_EXPLANATION    = 0
SHORT_EXPLANATION = 1
LONG_EXPLANATION  = 2

class PolicyGenerator:
    """Generate a reference policy module from access vectors.

    PolicyGenerator generates a new reference policy module
    or updates an existing module based on requested access
    in the form of access vectors.

    It generates allow rules and optionally module require
    statements and reference policy interfaces. By default
    only allow rules are generated. The methods .set_gen_refpol
    and .set_gen_requires turns on interface generation and
    requires generation respectively.

    PolicyGenerator can also optionally add comments explaining
    why a particular access was allowed based on the audit
    messages that generated the access. The access vectors
    passed in must have the .audit_msgs field set correctly
    and .explain set to SHORT|LONG_EXPLANATION to enable this
    feature.

    The module created by PolicyGenerator can be passed to
    output.ModuleWriter to output a text representation.
    """
    def __init__(self, module=None):
        """Initialize a PolicyGenerator with an optional
        existing module.

        If the module paramater is not None then access
        will be added to the passed in module. Otherwise
        a new reference policy module will be created.
        """
        self.ifgen = None
        self.explain = NO_EXPLANATION
        self.gen_requires = False
        if module:
            self.moduel = module
        else:
            self.module = refpolicy.Module()

        self.dontaudit = False

        self.domains = None
    def set_gen_refpol(self, if_set=None, perm_maps=None):
        """Set whether reference policy interfaces are generated.

        To turn on interface generation pass in an interface set
        to use for interface generation. To turn off interface
        generation pass in None.

        If interface generation is enabled requires generation
        will also be enabled.
        """
        if if_set:
            self.ifgen = InterfaceGenerator(if_set, perm_maps)
            self.gen_requires = True
        else:
            self.ifgen = None
        self.__set_module_style()


    def set_gen_requires(self, status=True):
        """Set whether module requires are generated.

        Passing in true will turn on requires generation and
        False will disable generation. If requires generation is
        disabled interface generation will also be disabled and
        can only be re-enabled via .set_gen_refpol.
        """
        self.gen_requires = status

    def set_gen_explain(self, explain=SHORT_EXPLANATION):
        """Set whether access is explained.
        """
        self.explain = explain

    def set_gen_dontaudit(self, dontaudit):
        self.dontaudit = dontaudit

    def __set_module_style(self):
        if self.ifgen:
            refpolicy = True
        else:
            refpolicy = False
        for mod in self.module.module_declarations():
            mod.refpolicy = refpolicy

    def set_module_name(self, name, version="1.0"):
        """Set the name of the module and optionally the version.
        """
        # find an existing module declaration
        m = None
        for mod in self.module.module_declarations():
            m = mod
        if not m:
            m = refpolicy.ModuleDeclaration()
            self.module.children.insert(0, m)
        m.name = name
        m.version = version
        if self.ifgen:
            m.refpolicy = True
        else:
            m.refpolicy = False

    def get_module(self):
        # Generate the requires
        if self.gen_requires:
            gen_requires(self.module)

        """Return the generated module"""
        return self.module

    def __add_allow_rules(self, avs):
        for av in avs:
            rule = refpolicy.AVRule(av)
            if self.dontaudit:
                rule.rule_type = rule.DONTAUDIT
            rule.comment = ""
            if self.explain:
                rule.comment = str(refpolicy.Comment(explain_access(av, verbosity=self.explain)))
            if av.type == audit2why.ALLOW:
                rule.comment += "\n#!!!! This avc is allowed in the current policy"
            if av.type == audit2why.DONTAUDIT:
                rule.comment += "\n#!!!! This avc has a dontaudit rule in the current policy"

            if av.type == audit2why.BOOLEAN:
                if len(av.data) > 1:
                    rule.comment += "\n#!!!! This avc can be allowed using one of the these booleans:\n#     %s" % ", ".join(map(lambda x: x[0], av.data))
                else:
                    rule.comment += "\n#!!!! This avc can be allowed using the boolean '%s'" % av.data[0][0]

            if av.type == audit2why.CONSTRAINT:
                rule.comment += "\n#!!!! This avc is a constraint violation.  You would need to modify the attributes of either the source or target types to allow this access."
                rule.comment += "\n#Constraint rule: "
                rule.comment += "\n\t" + av.data[0]
                for reason in av.data[1:]:
                    rule.comment += "\n#\tPossible cause is the source %s and target %s are different." % reason

            try:
                if ( av.type == audit2why.TERULE and
                     "write" in av.perms and
                     ( "dir" in av.obj_class or "open" in av.perms )):
                    if not self.domains:
                        self.domains = seinfo(ATTRIBUTE, name="domain")[0]["types"]
                    types=[]

                    for i in map(lambda x: x[TCONTEXT], sesearch([ALLOW], {SCONTEXT: av.src_type, CLASS: av.obj_class, PERMS: av.perms})):
                        if i not in self.domains:
                            types.append(i)
                    if len(types) == 1:
                        rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following type:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types))
                    elif len(types) >= 1:
                        rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following types:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types))
            except:
                pass
            self.module.children.append(rule)


    def add_access(self, av_set):
        """Add the access from the access vector set to this
        module.
        """
        # Use the interface generator to split the access
        # into raw allow rules and interfaces. After this
        # a will contain a list of access that should be
        # used as raw allow rules and the interfaces will
        # be added to the module.
        if self.ifgen:
            raw_allow, ifcalls = self.ifgen.gen(av_set, self.explain)
            self.module.children.extend(ifcalls)
        else:
            raw_allow = av_set

        # Generate the raw allow rules from the filtered list
        self.__add_allow_rules(raw_allow)

    def add_role_types(self, role_type_set):
        for role_type in role_type_set:
            self.module.children.append(role_type)

def explain_access(av, ml=None, verbosity=SHORT_EXPLANATION):
    """Explain why a policy statement was generated.

    Return a string containing a text explanation of
    why a policy statement was generated. The string is
    commented and wrapped and can be directly inserted
    into a policy.

    Params:
      av - access vector representing the access. Should
       have .audit_msgs set appropriately.
      verbosity - the amount of explanation provided. Should
       be set to NO_EXPLANATION, SHORT_EXPLANATION, or
       LONG_EXPLANATION.
    Returns:
      list of strings - strings explaining the access or an empty
       string if verbosity=NO_EXPLANATION or there is not sufficient
       information to provide an explanation.
    """
    s = []

    def explain_interfaces():
        if not ml:
            return
        s.append(" Interface options:")
        for match in ml.all():
            ifcall = call_interface(match.interface, ml.av)
            s.append('   %s # [%d]' % (ifcall.to_string(), match.dist))


    # Format the raw audit data to explain why the
    # access was requested - either long or short.
    if verbosity == LONG_EXPLANATION:
        for msg in av.audit_msgs:
            s.append(' %s' % msg.header)
            s.append('  scontext="%s" tcontext="%s"' %
                     (str(msg.scontext), str(msg.tcontext)))
            s.append('  class="%s" perms="%s"' %
                     (msg.tclass, refpolicy.list_to_space_str(msg.accesses)))
            s.append('  comm="%s" exe="%s" path="%s"' % (msg.comm, msg.exe, msg.path))
            s.extend(textwrap.wrap('message="' + msg.message + '"', 80, initial_indent="  ",
                                   subsequent_indent="   "))
        explain_interfaces()
    elif verbosity:
        s.append(' src="%s" tgt="%s" class="%s", perms="%s"' %
                 (av.src_type, av.tgt_type, av.obj_class, av.perms.to_space_str()))
        # For the short display we are only going to use the additional information
        # from the first audit message. For the vast majority of cases this info
        # will always be the same anyway.
        if len(av.audit_msgs) > 0:
            msg = av.audit_msgs[0]
            s.append(' comm="%s" exe="%s" path="%s"' % (msg.comm, msg.exe, msg.path))
        explain_interfaces()
    return s

def param_comp(a, b):
    return cmp(b.num, a.num)

def call_interface(interface, av):
    params = []
    args = []

    params.extend(interface.params.values())
    params.sort(param_comp)

    ifcall = refpolicy.InterfaceCall()
    ifcall.ifname = interface.name

    for i in range(len(params)):
        if params[i].type == refpolicy.SRC_TYPE:
            ifcall.args.append(av.src_type)
        elif params[i].type == refpolicy.TGT_TYPE:
            ifcall.args.append(av.tgt_type)
        elif params[i].type == refpolicy.OBJ_CLASS:
            ifcall.args.append(av.obj_class)
        else:
            print params[i].type
            assert(0)

    assert(len(ifcall.args) > 0)

    return ifcall

class InterfaceGenerator:
    def __init__(self, ifs, perm_maps=None):
        self.ifs = ifs
        self.hack_check_ifs(ifs)
        self.matcher = matching.AccessMatcher(perm_maps)
        self.calls = []

    def hack_check_ifs(self, ifs):
        # FIXME: Disable interfaces we can't call - this is a hack.
        # Because we don't handle roles, multiple paramaters, etc.,
        # etc., we must make certain we can actually use a returned
        # interface.
        for x in ifs.interfaces.values():
            params = []
            params.extend(x.params.values())
            params.sort(param_comp)
            for i in range(len(params)):
                # Check that the paramater position matches
                # the number (e.g., $1 is the first arg). This
                # will fail if the parser missed something.
                if (i + 1) != params[i].num:
                    x.enabled = False
                    break
                # Check that we can handle the param type (currently excludes
                # roles.
                if params[i].type not in [refpolicy.SRC_TYPE, refpolicy.TGT_TYPE,
                                          refpolicy.OBJ_CLASS]:
                    x.enabled = False
                    break

    def gen(self, avs, verbosity):
        raw_av = self.match(avs)
        ifcalls = []
        for ml in self.calls:
            ifcall = call_interface(ml.best().interface, ml.av)
            if verbosity:
                ifcall.comment = refpolicy.Comment(explain_access(ml.av, ml, verbosity))
            ifcalls.append((ifcall, ml))

        d = []
        for ifcall, ifs in ifcalls:
            found = False
            for o_ifcall in d:
                if o_ifcall.matches(ifcall):
                    if o_ifcall.comment and ifcall.comment:
                        o_ifcall.comment.merge(ifcall.comment)
                    found = True
            if not found:
                d.append(ifcall)

        return (raw_av, d)


    def match(self, avs):
        raw_av = []
        for av in avs:
            ans = matching.MatchList()
            self.matcher.search_ifs(self.ifs, av, ans)
            if len(ans):
                self.calls.append(ans)
            else:
                raw_av.append(av)

        return raw_av


def gen_requires(module):
    """Add require statements to the module.
    """
    def collect_requires(node):
        r = refpolicy.Require()
        for avrule in node.avrules():
            r.types.update(avrule.src_types)
            r.types.update(avrule.tgt_types)
            for obj in avrule.obj_classes:
                r.add_obj_class(obj, avrule.perms)

        for ifcall in node.interface_calls():
            for arg in ifcall.args:
                # FIXME - handle non-type arguments when we
                # can actually figure those out.
                r.types.add(arg)

        for role_type in node.role_types():
            r.roles.add(role_type.role)
            r.types.update(role_type.types)
                
        r.types.discard("self")

        node.children.insert(0, r)

    # FUTURE - this is untested on modules with any sort of
    # nesting
    for node in module.nodes():
        collect_requires(node)


