Home | History | Annotate | Download | only in policyrep
      1 # Copyright 2014-2016, Tresys Technology, LLC
      2 #
      3 # This file is part of SETools.
      4 #
      5 # SETools is free software: you can redistribute it and/or modify
      6 # it under the terms of the GNU Lesser General Public License as
      7 # published by the Free Software Foundation, either version 2.1 of
      8 # the License, or (at your option) any later version.
      9 #
     10 # SETools is distributed in the hope that it will be useful,
     11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 # GNU Lesser General Public License for more details.
     14 #
     15 # You should have received a copy of the GNU Lesser General Public
     16 # License along with SETools.  If not, see
     17 # <http://www.gnu.org/licenses/>.
     18 #
     19 import itertools
     20 
     21 from . import exception
     22 from . import qpol
     23 from . import rule
     24 from . import typeattr
     25 from . import boolcond
     26 
     27 
     28 def te_rule_factory(policy, symbol):
     29     """Factory function for creating TE rule objects."""
     30 
     31     if isinstance(symbol, qpol.qpol_avrule_t):
     32         return AVRule(policy, symbol)
     33     elif isinstance(symbol, (qpol.qpol_terule_t, qpol.qpol_filename_trans_t)):
     34         return TERule(policy, symbol)
     35     else:
     36         raise TypeError("TE rules cannot be looked-up.")
     37 
     38 
     39 def expanded_te_rule_factory(original, source, target):
     40     """
     41     Factory function for creating expanded TE rules.
     42 
     43     original    The TE rule the expanded rule originates from.
     44     source      The source type of the expanded rule.
     45     target      The target type of the expanded rule.
     46     """
     47 
     48     if isinstance(original, AVRule):
     49         rule = ExpandedAVRule(original.policy, original.qpol_symbol)
     50     elif isinstance(original, TERule):
     51         rule = ExpandedTERule(original.policy, original.qpol_symbol)
     52     elif isinstance(original, (ExpandedAVRule, ExpandedTERule)):
     53         return original
     54     else:
     55         raise TypeError("The original rule must be a TE rule class.")
     56 
     57     rule.source = source
     58     rule.target = target
     59     rule.origin = original
     60     return rule
     61 
     62 
     63 def validate_ruletype(t):
     64     """Validate TE Rule types."""
     65     if t not in ["allow", "auditallow", "dontaudit", "neverallow",
     66                  "type_transition", "type_member", "type_change"]:
     67         raise exception.InvalidTERuleType("{0} is not a valid TE rule type.".format(t))
     68 
     69     return t
     70 
     71 
     72 class BaseTERule(rule.PolicyRule):
     73 
     74     """A type enforcement rule."""
     75 
     76     @property
     77     def source(self):
     78         """The rule's source type/attribute."""
     79         return typeattr.type_or_attr_factory(self.policy, self.qpol_symbol.source_type(self.policy))
     80 
     81     @property
     82     def target(self):
     83         """The rule's target type/attribute."""
     84         return typeattr.type_or_attr_factory(self.policy, self.qpol_symbol.target_type(self.policy))
     85 
     86     @property
     87     def filename(self):
     88         raise NotImplementedError
     89 
     90     @property
     91     def conditional(self):
     92         """The rule's conditional expression."""
     93         try:
     94             return boolcond.condexpr_factory(self.policy, self.qpol_symbol.cond(self.policy))
     95         except (AttributeError, ValueError):
     96             # AttributeError: name filetrans rules cannot be conditional
     97             #                 so no member function
     98             # ValueError:     The rule is not conditional
     99             raise exception.RuleNotConditional
    100 
    101     @property
    102     def conditional_block(self):
    103         """The conditional block of the rule (T/F)"""
    104         try:
    105             return bool(self.qpol_symbol.which_list(self.policy))
    106         except (AttributeError, ValueError):
    107             # AttributeError: name filetrans rules cannot be conditional
    108             #                 so no member function
    109             # ValueError:     The rule is not conditional
    110             raise exception.RuleNotConditional
    111 
    112     def expand(self):
    113         """Expand the rule into an equivalent set of rules without attributes."""
    114         for s, t in itertools.product(self.source.expand(), self.target.expand()):
    115             yield expanded_te_rule_factory(self, s, t)
    116 
    117 
    118 class AVRule(BaseTERule):
    119 
    120     """An access vector type enforcement rule."""
    121 
    122     def __str__(self):
    123         try:
    124             return self._rule_string
    125         except AttributeError:
    126             self._rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} ".format(self)
    127 
    128             perms = self.perms
    129 
    130             # allow/dontaudit/auditallow/neverallow rules
    131             if len(perms) > 1:
    132                 self._rule_string += "{{ {0} }};".format(' '.join(perms))
    133             else:
    134                 # convert to list since sets cannot be indexed
    135                 self._rule_string += "{0};".format(list(perms)[0])
    136 
    137             try:
    138                 self._rule_string += " [ {0.conditional} ]:{0.conditional_block}".format(self)
    139             except exception.RuleNotConditional:
    140                 pass
    141 
    142         return self._rule_string
    143 
    144     @property
    145     def perms(self):
    146         """The rule's permission set."""
    147         return set(self.qpol_symbol.perm_iter(self.policy))
    148 
    149     @property
    150     def default(self):
    151         """The rule's default type."""
    152         raise exception.RuleUseError("{0} rules do not have a default type.".format(self.ruletype))
    153 
    154     @property
    155     def filename(self):
    156         raise exception.RuleUseError("{0} rules do not have file names".format(self.ruletype))
    157 
    158 
    159 class TERule(BaseTERule):
    160 
    161     """A type_* type enforcement rule."""
    162 
    163     def __str__(self):
    164         try:
    165             return self._rule_string
    166         except AttributeError:
    167             self._rule_string = "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.default}".format(
    168                 self)
    169 
    170             try:
    171                 self._rule_string += " \"{0}\";".format(self.filename)
    172             except (exception.TERuleNoFilename, exception.RuleUseError):
    173                 # invalid use for type_change/member
    174                 self._rule_string += ";"
    175 
    176             try:
    177                 self._rule_string += " [ {0.conditional} ]:{0.conditional_block}".format(self)
    178             except exception.RuleNotConditional:
    179                 pass
    180 
    181             return self._rule_string
    182 
    183     def __hash__(self):
    184         try:
    185             cond = self.conditional
    186             cond_block = self.conditional_block
    187         except exception.RuleNotConditional:
    188             cond = None
    189             cond_block = None
    190 
    191         try:
    192             filename = self.filename
    193         except (exception.TERuleNoFilename, exception.RuleUseError):
    194             filename = None
    195 
    196         return hash("{0.ruletype}|{0.source}|{0.target}|{0.tclass}|{1}|{2}|{3}".format(
    197             self, filename, cond, cond_block))
    198 
    199     @property
    200     def perms(self):
    201         """The rule's permission set."""
    202         raise exception.RuleUseError(
    203             "{0} rules do not have a permission set.".format(self.ruletype))
    204 
    205     @property
    206     def default(self):
    207         """The rule's default type."""
    208         return typeattr.type_factory(self.policy, self.qpol_symbol.default_type(self.policy))
    209 
    210     @property
    211     def filename(self):
    212         """The type_transition rule's file name."""
    213         try:
    214             return self.qpol_symbol.filename(self.policy)
    215         except AttributeError:
    216             if self.ruletype == "type_transition":
    217                 raise exception.TERuleNoFilename
    218             else:
    219                 raise exception.RuleUseError("{0} rules do not have file names".
    220                                              format(self.ruletype))
    221 
    222 
    223 class ExpandedAVRule(AVRule):
    224 
    225     """An expanded access vector type enforcement rule."""
    226 
    227     source = None
    228     target = None
    229     origin = None
    230 
    231 
    232 class ExpandedTERule(TERule):
    233 
    234     """An expanded type_* type enforcement rule."""
    235 
    236     source = None
    237     target = None
    238     origin = None
    239