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 role
     25 from . import typeattr
     26 
     27 
     28 def rbac_rule_factory(policy, name):
     29     """Factory function for creating RBAC rule objects."""
     30 
     31     if isinstance(name, qpol.qpol_role_allow_t):
     32         return RoleAllow(policy, name)
     33     elif isinstance(name, qpol.qpol_role_trans_t):
     34         return RoleTransition(policy, name)
     35     else:
     36         raise TypeError("RBAC rules cannot be looked up.")
     37 
     38 
     39 def expanded_rbac_rule_factory(original, source, target):
     40     """
     41     Factory function for creating expanded RBAC rules.
     42 
     43     original    The RBAC 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, (ExpandedRoleAllow, ExpandedRoleTransition)):
     49         return original
     50     elif isinstance(original, RoleAllow):
     51         rule = ExpandedRoleAllow(original.policy, original.qpol_symbol)
     52     elif isinstance(original, RoleTransition):
     53         rule = ExpandedRoleTransition(original.policy, original.qpol_symbol)
     54     else:
     55         raise TypeError("The original rule must be an RBAC 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 RBAC rule types."""
     65     if t not in ["allow", "role_transition"]:
     66         raise exception.InvalidRBACRuleType("{0} is not a valid RBAC rule type.".format(t))
     67 
     68     return t
     69 
     70 
     71 class RoleAllow(rule.PolicyRule):
     72 
     73     """A role allow rule."""
     74 
     75     def __str__(self):
     76         return "{0.ruletype} {0.source} {0.target};".format(self)
     77 
     78     def __hash__(self):
     79         return hash("{0.ruletype}|{0.source}|{0.target}".format(self))
     80 
     81     ruletype = "allow"
     82 
     83     @property
     84     def source(self):
     85         """The rule's source role."""
     86         return role.role_factory(self.policy, self.qpol_symbol.source_role(self.policy))
     87 
     88     @property
     89     def target(self):
     90         """The rule's target role."""
     91         return role.role_factory(self.policy, self.qpol_symbol.target_role(self.policy))
     92 
     93     @property
     94     def tclass(self):
     95         """The rule's object class."""
     96         raise exception.RuleUseError("Role allow rules do not have an object class.")
     97 
     98     @property
     99     def default(self):
    100         """The rule's default role."""
    101         raise exception.RuleUseError("Role allow rules do not have a default role.")
    102 
    103     def expand(self):
    104         """Expand the rule into an equivalent set of rules without attributes."""
    105         for s, t in itertools.product(self.source.expand(), self.target.expand()):
    106             yield expanded_rbac_rule_factory(self, s, t)
    107 
    108 
    109 class RoleTransition(rule.PolicyRule):
    110 
    111     """A role_transition rule."""
    112 
    113     def __str__(self):
    114         return "{0.ruletype} {0.source} {0.target}:{0.tclass} {0.default};".format(self)
    115 
    116     ruletype = "role_transition"
    117 
    118     @property
    119     def source(self):
    120         """The rule's source role."""
    121         return role.role_factory(self.policy, self.qpol_symbol.source_role(self.policy))
    122 
    123     @property
    124     def target(self):
    125         """The rule's target type/attribute."""
    126         return typeattr.type_or_attr_factory(self.policy, self.qpol_symbol.target_type(self.policy))
    127 
    128     @property
    129     def default(self):
    130         """The rule's default role."""
    131         return role.role_factory(self.policy, self.qpol_symbol.default_role(self.policy))
    132 
    133     def expand(self):
    134         """Expand the rule into an equivalent set of rules without attributes."""
    135         for s, t in itertools.product(self.source.expand(), self.target.expand()):
    136             yield expanded_rbac_rule_factory(self, s, t)
    137 
    138 
    139 class ExpandedRoleAllow(RoleAllow):
    140 
    141     """An expanded role allow rule."""
    142 
    143     source = None
    144     target = None
    145     origin = None
    146 
    147 
    148 class ExpandedRoleTransition(RoleTransition):
    149 
    150     """An expanded role_transition rule."""
    151 
    152     source = None
    153     target = None
    154     origin = None
    155