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# 19import itertools 20 21from . import exception 22from . import qpol 23from . import rule 24from . import role 25from . import typeattr 26 27 28def 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 39def 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 63def 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 71class 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 109class 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 139class ExpandedRoleAllow(RoleAllow): 140 141 """An expanded role allow rule.""" 142 143 source = None 144 target = None 145 origin = None 146 147 148class ExpandedRoleTransition(RoleTransition): 149 150 """An expanded role_transition rule.""" 151 152 source = None 153 target = None 154 origin = None 155