# Copyright 2014-2016, Tresys Technology, LLC
#
# This file is part of SETools.
#
# SETools is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 2.1 of
# the License, or (at your option) any later version.
#
# SETools 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with SETools.  If not, see
# <http://www.gnu.org/licenses/>.
#
# pylint: disable=too-many-public-methods
#
# Create a Python representation of the policy.
# The idea is that this is module provides convenient
# abstractions and methods for accessing the policy
# structures.
import logging
from itertools import chain
from errno import ENOENT

try:
    import selinux
except ImportError:
    pass

from . import qpol

# The libqpol SWIG class is not quite natural for
# Python the policy is repeatedly referenced in the
# function calls, which makes sense for C code
# but not for python code, so each object keeps
# a reference to the policy for internal use.
# This also makes sense since an object would only
# be valid for the policy it comes from.

# Components
from . import boolcond
from . import bounds
from . import default
from . import mls
from . import objclass
from . import polcap
from . import role
from . import typeattr
from . import user

# Rules
from . import mlsrule
from . import rbacrule
from . import terule

# Constraints
from . import constraint

# In-policy Labeling
from . import fscontext
from . import initsid
from . import netcontext

# Xen
from . import xencontext

# Classes useful for policyrep users:
from . import exception
from .netcontext import PortconProtocol, port_range
from .terule import ioctlSet


class SELinuxPolicy(object):

    """The complete SELinux policy."""

    def __init__(self, policyfile=None):
        """
        Parameter:
        policyfile  Path to a policy to open.
        """

        self.log = logging.getLogger(__name__)
        self.policy = None
        self.filename = None

        if policyfile:
            self._load_policy(policyfile)
        else:
            try:
                self._load_running_policy()
            except NameError:
                raise RuntimeError("Loading the running policy requires libselinux Python bindings")

    def __repr__(self):
        return "<SELinuxPolicy(\"{0}\")>".format(self.filename)

    def __str__(self):
        return self.filename

    def __deepcopy__(self, memo):
        # shallow copy as all of the members are immutable
        newobj = SELinuxPolicy.__new__(SELinuxPolicy)
        newobj.policy = self.policy
        newobj.filename = self.filename
        memo[id(self)] = newobj
        return newobj

    #
    # Policy loading functions
    #

    def _load_policy(self, filename):
        """Load the specified policy."""
        self.log.info("Opening SELinux policy \"{0}\"".format(filename))

        try:
            self.policy = qpol.qpol_policy_factory(str(filename))
        except SyntaxError as err:
            raise exception.InvalidPolicy("Error opening policy file \"{0}\": {1}".
                                          format(filename, err))

        self.log.info("Successfully opened SELinux policy \"{0}\"".format(filename))
        self.filename = filename

    @staticmethod
    def _potential_policies():
        """Generate a list of potential policies to use."""
        # try libselinux for current policy
        if selinux.selinuxfs_exists():
            yield selinux.selinux_current_policy_path()

        # otherwise look through the supported policy versions
        base_policy_path = selinux.selinux_binary_policy_path()
        for version in range(qpol.QPOL_POLICY_MAX_VERSION, qpol.QPOL_POLICY_MIN_VERSION-1, -1):
            yield "{0}.{1}".format(base_policy_path, version)

    def _load_running_policy(self):
        """Try to load the current running policy."""
        self.log.info("Attempting to locate current running policy.")

        for filename in self._potential_policies():
            try:
                self._load_policy(filename)
            except OSError as err:
                if err.errno != ENOENT:
                    raise
            else:
                break
        else:
            raise RuntimeError("Unable to locate an SELinux policy to load.")

    #
    # Policy properties
    #
    @property
    def handle_unknown(self):
        """The handle unknown permissions setting (allow,deny,reject)"""
        return self.policy.handle_unknown()

    @property
    def mls(self):
        """(T/F) The policy has MLS enabled."""
        return mls.enabled(self.policy)

    @property
    def version(self):
        """The policy database version (e.g. v29)"""
        return self.policy.version()

    @property
    def target_platform(self):
        """The policy platform (selinux or xen)"""
        return self.policy.target_platform()

    #
    # Policy statistics
    #

    @property
    def allow_count(self):
        """The number of (type) allow rules."""
        return self.policy.avrule_allow_count()

    @property
    def allowxperm_count(self):
        """The number of allowxperm rules."""
        return self.policy.avrule_allowx_count()

    @property
    def auditallow_count(self):
        """The number of auditallow rules."""
        return self.policy.avrule_auditallow_count()

    @property
    def auditallowxperm_count(self):
        """The number of auditallowxperm rules."""
        return self.policy.avrule_auditallowx_count()

    @property
    def boolean_count(self):
        """The number of Booleans."""
        return self.policy.bool_count()

    @property
    def category_count(self):
        """The number of categories."""
        return sum(1 for _ in self.categories())

    @property
    def class_count(self):
        """The number of object classes."""
        return self.policy.class_count()

    @property
    def common_count(self):
        """The number of common permission sets."""
        return self.policy.common_count()

    @property
    def conditional_count(self):
        """The number of conditionals."""
        return self.policy.cond_count()

    @property
    def constraint_count(self):
        """The number of standard constraints."""
        return sum(1 for c in self.constraints() if c.ruletype == "constrain")

    @property
    def default_count(self):
        """The number of default_* rules."""
        return sum(1 for d in self.defaults())

    @property
    def devicetreecon_count(self):
        """The number of Xen devicetreecon statements."""
        return self.policy.devicetreecon_count()

    @property
    def dontaudit_count(self):
        """The number of dontaudit rules."""
        return self.policy.avrule_dontaudit_count()

    @property
    def dontauditxperm_count(self):
        """The number of dontauditxperm rules."""
        return self.policy.avrule_dontauditx_count()

    @property
    def fs_use_count(self):
        """fs_use_* statements."""
        return self.policy.fs_use_count()

    @property
    def genfscon_count(self):
        """The number of genfscon statements."""
        return self.policy.genfscon_count()

    @property
    def initialsids_count(self):
        """The number of initial sid statements."""
        return self.policy.isid_count()

    @property
    def iomemcon_count(self):
        """The number of Xen iomemcon statements."""
        return self.policy.iomemcon_count()

    @property
    def ioportcon_count(self):
        """The number of Xen ioportcon statements."""
        return self.policy.ioportcon_count()

    @property
    def level_count(self):
        """The number of levels."""
        return sum(1 for _ in self.levels())

    @property
    def mlsconstraint_count(self):
        """The number of MLS constraints."""
        return sum(1 for c in self.constraints() if c.ruletype == "mlsconstrain")

    @property
    def mlsvalidatetrans_count(self):
        """The number of MLS validatetrans."""
        return sum(1 for v in self.constraints() if v.ruletype == "mlsvalidatetrans")

    @property
    def netifcon_count(self):
        """The number of netifcon statements."""
        return self.policy.netifcon_count()

    @property
    def neverallow_count(self):
        """The number of neverallow rules."""
        return self.policy.avrule_neverallow_count()

    @property
    def neverallowxperm_count(self):
        """The number of neverallowxperm rules."""
        return self.policy.avrule_neverallowx_count()

    @property
    def nodecon_count(self):
        """The number of nodecon statements."""
        return self.policy.nodecon_count()

    @property
    def pcidevicecon_count(self):
        """The number of Xen pcidevicecon statements."""
        return self.policy.pcidevicecon_count()

    @property
    def permission_count(self):
        """The number of permissions."""
        return sum(len(c.perms) for c in chain(self.commons(), self.classes()))

    @property
    def permissives_count(self):
        """The number of permissive types."""
        return self.policy.permissive_count()

    @property
    def pirqcon_count(self):
        """The number of Xen pirqcon statements."""
        return self.policy.pirqcon_count()

    @property
    def polcap_count(self):
        """The number of policy capabilities."""
        return self.policy.polcap_count()

    @property
    def portcon_count(self):
        """The number of portcon statements."""
        return self.policy.portcon_count()

    @property
    def range_transition_count(self):
        """The number of range_transition rules."""
        return self.policy.range_trans_count()

    @property
    def role_count(self):
        """The number of roles."""
        return self.policy.role_count()

    @property
    def role_allow_count(self):
        """The number of (role) allow rules."""
        return self.policy.role_allow_count()

    @property
    def role_transition_count(self):
        """The number of role_transition rules."""
        return self.policy.role_trans_count()

    @property
    def type_attribute_count(self):
        """The number of (type) attributes."""
        return sum(1 for _ in self.typeattributes())

    @property
    def type_count(self):
        """The number of types."""
        return sum(1 for _ in self.types())

    @property
    def type_change_count(self):
        """The number of type_change rules."""
        return self.policy.terule_change_count()

    @property
    def type_member_count(self):
        """The number of type_member rules."""
        return self.policy.terule_member_count()

    @property
    def type_transition_count(self):
        """The number of type_transition rules."""
        return self.policy.terule_trans_count() + self.policy.filename_trans_count()

    @property
    def typebounds_count(self):
        """The number of typebounds rules."""
        return sum(1 for b in self.bounds() if b.ruletype == "typebounds")

    @property
    def user_count(self):
        """The number of users."""
        return self.policy.user_count()

    @property
    def validatetrans_count(self):
        """The number of validatetrans."""
        return sum(1 for v in self.constraints() if v.ruletype == "validatetrans")

    #
    # Policy components lookup functions
    #
    def lookup_boolean(self, name):
        """Look up a Boolean."""
        return boolcond.boolean_factory(self.policy, name)

    def lookup_class(self, name):
        """Look up an object class."""
        return objclass.class_factory(self.policy, name)

    def lookup_common(self, name):
        """Look up a common permission set."""
        return objclass.common_factory(self.policy, name)

    def lookup_initialsid(self, name):
        """Look up an initial sid."""
        return initsid.initialsid_factory(self.policy, name)

    def lookup_level(self, level):
        """Look up a MLS level."""
        return mls.level_factory(self.policy, level)

    def lookup_sensitivity(self, name):
        """Look up a MLS sensitivity by name."""
        return mls.sensitivity_factory(self.policy, name)

    def lookup_range(self, range_):
        """Look up a MLS range."""
        return mls.range_factory(self.policy, range_)

    def lookup_role(self, name):
        """Look up a role by name."""
        return role.role_factory(self.policy, name)

    def lookup_type(self, name):
        """Look up a type by name."""
        return typeattr.type_factory(self.policy, name, deref=True)

    def lookup_type_or_attr(self, name):
        """Look up a type or type attribute by name."""
        return typeattr.type_or_attr_factory(self.policy, name, deref=True)

    def lookup_typeattr(self, name):
        """Look up a type attribute by name."""
        return typeattr.attribute_factory(self.policy, name)

    def lookup_user(self, name):
        """Look up a user by name."""
        return user.user_factory(self.policy, name)

    #
    # Policy components generators
    #

    def bools(self):
        """Generator which yields all Booleans."""
        for bool_ in self.policy.bool_iter():
            yield boolcond.boolean_factory(self.policy, bool_)

    def bounds(self):
        """Generator which yields all *bounds statements (typebounds, etc.)"""
        for bound in self.policy.typebounds_iter():
            yield bounds.bounds_factory(self.policy, bound)

    def categories(self):
        """Generator which yields all MLS categories."""
        for cat in self.policy.cat_iter():
            try:
                yield mls.category_factory(self.policy, cat)
            except TypeError:
                # libqpol unfortunately iterates over aliases too
                pass

    def classes(self):
        """Generator which yields all object classes."""
        for class_ in self.policy.class_iter():
            yield objclass.class_factory(self.policy, class_)

    def commons(self):
        """Generator which yields all commons."""
        for common in self.policy.common_iter():
            yield objclass.common_factory(self.policy, common)

    def defaults(self):
        """Generator which yields all default_* statements."""
        for default_ in self.policy.default_iter():
            try:
                for default_obj in default.default_factory(self.policy, default_):
                    yield default_obj
            except exception.NoDefaults:
                # qpol iterates over all classes. Handle case
                # where a class has no default_* settings.
                pass

    def levels(self):
        """Generator which yields all level declarations."""
        for level in self.policy.level_iter():

            try:
                yield mls.level_decl_factory(self.policy, level)
            except TypeError:
                # libqpol unfortunately iterates over levels and sens aliases
                pass

    def polcaps(self):
        """Generator which yields all policy capabilities."""
        for cap in self.policy.polcap_iter():
            yield polcap.polcap_factory(self.policy, cap)

    def roles(self):
        """Generator which yields all roles."""
        for role_ in self.policy.role_iter():
            yield role.role_factory(self.policy, role_)

    def sensitivities(self):
        """Generator which yields all sensitivities."""
        # see mls.py for more info on why level_iter is used here.
        for sens in self.policy.level_iter():
            try:
                yield mls.sensitivity_factory(self.policy, sens)
            except TypeError:
                # libqpol unfortunately iterates over sens and aliases
                pass

    def types(self):
        """Generator which yields all types."""
        for type_ in self.policy.type_iter():
            try:
                yield typeattr.type_factory(self.policy, type_)
            except TypeError:
                # libqpol unfortunately iterates over attributes and aliases
                pass

    def typeattributes(self):
        """Generator which yields all (type) attributes."""
        for type_ in self.policy.type_iter():
            try:
                yield typeattr.attribute_factory(self.policy, type_)
            except TypeError:
                # libqpol unfortunately iterates over attributes and aliases
                pass

    def users(self):
        """Generator which yields all users."""
        for user_ in self.policy.user_iter():
            yield user.user_factory(self.policy, user_)

    #
    # Policy rules generators
    #
    def mlsrules(self):
        """Generator which yields all MLS rules."""
        for rule in self.policy.range_trans_iter():
            yield mlsrule.mls_rule_factory(self.policy, rule)

    def rbacrules(self):
        """Generator which yields all RBAC rules."""
        for rule in chain(self.policy.role_allow_iter(),
                          self.policy.role_trans_iter()):
            yield rbacrule.rbac_rule_factory(self.policy, rule)

    def terules(self):
        """Generator which yields all type enforcement rules."""
        for rule in chain(self.policy.avrule_iter(),
                          self.policy.avrulex_iter(),
                          self.policy.terule_iter(),
                          self.policy.filename_trans_iter()):
            yield terule.te_rule_factory(self.policy, rule)

    #
    # Policy rule type validators
    #
    @staticmethod
    def validate_bounds_ruletype(types):
        """Validate constraint types."""
        return bounds.validate_ruletype(types)

    @staticmethod
    def validate_constraint_ruletype(types):
        """Validate constraint types."""
        return constraint.validate_ruletype(types)

    @staticmethod
    def validate_default_ruletype(types):
        """Validate default_* types."""
        return default.validate_ruletype(types)

    @staticmethod
    def validate_default_value(value):
        """Validate default_* values."""
        return default.validate_default_value(value)

    @staticmethod
    def validate_default_range(value):
        """Validate default_range range."""
        return default.validate_default_range(value)

    @staticmethod
    def validate_fs_use_ruletype(types):
        """Validate fs_use_* rule types."""
        return fscontext.validate_ruletype(types)

    @staticmethod
    def validate_mls_ruletype(types):
        """Validate MLS rule types."""
        return mlsrule.validate_ruletype(types)

    @staticmethod
    def validate_rbac_ruletype(types):
        """Validate RBAC rule types."""
        return rbacrule.validate_ruletype(types)

    @staticmethod
    def validate_te_ruletype(types):
        """Validate type enforcement rule types."""
        return terule.validate_ruletype(types)

    #
    # Constraints generators
    #

    def constraints(self):
        """Generator which yields all constraints (regular and MLS)."""
        for constraint_ in chain(self.policy.constraint_iter(),
                                 self.policy.validatetrans_iter()):

            yield constraint.constraint_factory(self.policy, constraint_)

    #
    # In-policy Labeling statement generators
    #
    def fs_uses(self):
        """Generator which yields all fs_use_* statements."""
        for fs_use in self.policy.fs_use_iter():
            yield fscontext.fs_use_factory(self.policy, fs_use)

    def genfscons(self):
        """Generator which yields all genfscon statements."""
        for fscon in self.policy.genfscon_iter():
            yield fscontext.genfscon_factory(self.policy, fscon)

    def initialsids(self):
        """Generator which yields all initial SID statements."""
        for sid in self.policy.isid_iter():
            yield initsid.initialsid_factory(self.policy, sid)

    def netifcons(self):
        """Generator which yields all netifcon statements."""
        for ifcon in self.policy.netifcon_iter():
            yield netcontext.netifcon_factory(self.policy, ifcon)

    def nodecons(self):
        """Generator which yields all nodecon statements."""
        for node in self.policy.nodecon_iter():
            yield netcontext.nodecon_factory(self.policy, node)

    def portcons(self):
        """Generator which yields all portcon statements."""
        for port in self.policy.portcon_iter():
            yield netcontext.portcon_factory(self.policy, port)

    #
    # Xen labeling statements
    #
    def iomemcons(self):
        """Generator which yields all iomemcon statements."""
        for mem_addr in self.policy.iomemcon_iter():
            yield xencontext.iomemcon_factory(self.policy, mem_addr)

    def ioportcons(self):
        """Generator which yields all ioportcon statements."""
        for port in self.policy.ioportcon_iter():
            yield xencontext.ioportcon_factory(self.policy, port)

    def pcidevicecons(self):
        """Generator which yields all pcidevicecon statements."""
        for device in self.policy.pcidevicecon_iter():
            yield xencontext.pcidevicecon_factory(self.policy, device)

    def pirqcons(self):
        """Generator which yields all pirqcon statements."""
        for irq in self.policy.pirqcon_iter():
            yield xencontext.pirqcon_factory(self.policy, irq)

    def devicetreecons(self):
        """Generator which yields all devicetreecon statements."""
        for path in self.policy.devicetreecon_iter():
            yield xencontext.devicetreecon_factory(self.policy, path)
