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 from . import exception 20 from . import symbol 21 from . import objclass 22 from . import qpol 23 24 25 def validate_ruletype(t): 26 """Validate default_* rule types.""" 27 if t not in ["default_role", "default_range", "default_type", "default_user"]: 28 raise exception.InvalidDefaultType("{0} is not a valid default_* rule type.".format(t)) 29 30 return t 31 32 33 def validate_default_value(default): 34 if default not in ["source", "target"]: 35 raise exception.InvalidDefaultValue("{0} is not a valid default_* value.".format(default)) 36 37 return default 38 39 40 def validate_default_range(default): 41 if default not in ["low", "high", "low_high"]: 42 raise exception.InvalidDefaultRange("{0} is not a valid default_* range.".format(default)) 43 44 return default 45 46 47 def default_factory(policy, sym): 48 """Factory generator for creating default_* statement objects.""" 49 50 # The low level policy groups default_* settings by object class. 51 # Since each class can have up to four default_* statements, 52 # this factory function is a generator which yields up to 53 # four Default objects. 54 55 if not isinstance(sym, qpol.qpol_default_object_t): 56 raise NotImplementedError 57 58 # qpol will essentially iterate over all classes 59 # and emit None for classes that don't set a default. 60 # Because of all of this processing, extract almost 61 # all of the information out of the qpol representation. 62 # (we have to determine almost all of it anyway) 63 if not sym.object_class(policy): 64 raise exception.NoDefaults 65 66 user = sym.user_default(policy) 67 role = sym.role_default(policy) 68 type_ = sym.type_default(policy) 69 range_ = sym.range_default(policy) 70 71 if user: 72 obj = Default(policy, sym) 73 obj.ruletype = "default_user" 74 obj.default = user 75 yield obj 76 77 if role: 78 obj = Default(policy, sym) 79 obj.ruletype = "default_role" 80 obj.default = role 81 yield obj 82 83 if type_: 84 obj = Default(policy, sym) 85 obj.ruletype = "default_type" 86 obj.default = type_ 87 yield obj 88 89 if range_: 90 # range_ is something like "source low_high" 91 rng = range_.split() 92 obj = RangeDefault(policy, sym) 93 obj.ruletype = "default_range" 94 obj.default = rng[0] 95 obj.default_range = rng[1] 96 yield obj 97 98 99 class Default(symbol.PolicySymbol): 100 101 """Base class for default_* statements.""" 102 103 ruletype = None 104 default = None 105 106 def __str__(self): 107 return "{0.ruletype} {0.tclass} {0.default};".format(self) 108 109 def __hash__(self): 110 return hash("{0.ruletype}|{0.tclass}".format(self)) 111 112 @property 113 def tclass(self): 114 """The object class.""" 115 return objclass.class_factory(self.policy, self.qpol_symbol.object_class(self.policy)) 116 117 def statement(self): 118 return str(self) 119 120 121 class RangeDefault(Default): 122 123 """A default_range statement.""" 124 125 default_range = None 126 127 def __str__(self): 128 return "{0.ruletype} {0.tclass} {0.default} {0.default_range};".format(self) 129