1 # Copyright 2014-2015, 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 logging 20 import re 21 22 from . import mixins, query 23 from .descriptors import CriteriaDescriptor, CriteriaSetDescriptor 24 from .policyrep import ioctlSet 25 from .policyrep.exception import RuleUseError, RuleNotConditional 26 from .util import match_regex, match_indirect_regex, match_regex_or_set 27 28 29 class TERuleQuery(mixins.MatchObjClass, mixins.MatchPermission, query.PolicyQuery): 30 31 """ 32 Query the Type Enforcement rules. 33 34 Parameter: 35 policy The policy to query. 36 37 Keyword Parameters/Class attributes: 38 ruletype The list of rule type(s) to match. 39 source The name of the source type/attribute to match. 40 source_indirect If true, members of an attribute will be 41 matched rather than the attribute itself. 42 Default is true. 43 source_regex If true, regular expression matching will 44 be used on the source type/attribute. 45 Obeys the source_indirect option. 46 Default is false. 47 target The name of the target type/attribute to match. 48 target_indirect If true, members of an attribute will be 49 matched rather than the attribute itself. 50 Default is true. 51 target_regex If true, regular expression matching will 52 be used on the target type/attribute. 53 Obeys target_indirect option. 54 Default is false. 55 tclass The object class(es) to match. 56 tclass_regex If true, use a regular expression for 57 matching the rule's object class. 58 Default is false. 59 perms The set of permission(s) to match. 60 perms_equal If true, the permission set of the rule 61 must exactly match the permissions 62 criteria. If false, any set intersection 63 will match. 64 Default is false. 65 perms_regex If true, regular expression matching will be used 66 on the permission names instead of set logic. 67 Default is false. 68 perms_subset If true, the rule matches if the permissions criteria 69 is a subset of the rule's permission set. 70 Default is false. 71 default The name of the default type to match. 72 default_regex If true, regular expression matching will be 73 used on the default type. 74 Default is false. 75 boolean The set of boolean(s) to match. 76 boolean_regex If true, regular expression matching will be 77 used on the booleans. 78 Default is false. 79 boolean_equal If true, the booleans in the conditional 80 expression of the rule must exactly match the 81 criteria. If false, any set intersection 82 will match. Default is false. 83 """ 84 85 ruletype = CriteriaSetDescriptor(lookup_function="validate_te_ruletype") 86 source = CriteriaDescriptor("source_regex", "lookup_type_or_attr") 87 source_regex = False 88 source_indirect = True 89 target = CriteriaDescriptor("target_regex", "lookup_type_or_attr") 90 target_regex = False 91 target_indirect = True 92 default = CriteriaDescriptor("default_regex", "lookup_type_or_attr") 93 default_regex = False 94 boolean = CriteriaSetDescriptor("boolean_regex", "lookup_boolean") 95 boolean_regex = False 96 boolean_equal = False 97 _xperms = None 98 xperms_equal = False 99 100 @property 101 def xperms(self): 102 return self._xperms 103 104 @xperms.setter 105 def xperms(self, value): 106 if value: 107 pending_xperms = ioctlSet() 108 109 for low, high in value: 110 if not (0 <= low <= 0xffff): 111 raise ValueError("{0:#07x} is not a valid ioctl.".format(low)) 112 113 if not (0 <= high <= 0xffff): 114 raise ValueError("{0:#07x} is not a valid ioctl.".format(high)) 115 116 if high < low: 117 high, low = low, high 118 119 pending_xperms.update(i for i in range(low, high+1)) 120 121 self._xperms = pending_xperms 122 else: 123 self._xperms = None 124 125 def __init__(self, policy, **kwargs): 126 super(TERuleQuery, self).__init__(policy, **kwargs) 127 self.log = logging.getLogger(__name__) 128 129 def results(self): 130 """Generator which yields all matching TE rules.""" 131 self.log.info("Generating TE rule results from {0.policy}".format(self)) 132 self.log.debug("Ruletypes: {0.ruletype}".format(self)) 133 self.log.debug("Source: {0.source!r}, indirect: {0.source_indirect}, " 134 "regex: {0.source_regex}".format(self)) 135 self.log.debug("Target: {0.target!r}, indirect: {0.target_indirect}, " 136 "regex: {0.target_regex}".format(self)) 137 self._match_object_class_debug(self.log) 138 self._match_perms_debug(self.log) 139 self.log.debug("Xperms: {0.xperms!r}, eq: {0.xperms_equal}".format(self)) 140 self.log.debug("Default: {0.default!r}, regex: {0.default_regex}".format(self)) 141 self.log.debug("Boolean: {0.boolean!r}, eq: {0.boolean_equal}, " 142 "regex: {0.boolean_regex}".format(self)) 143 144 for rule in self.policy.terules(): 145 # 146 # Matching on rule type 147 # 148 if self.ruletype: 149 if rule.ruletype not in self.ruletype: 150 continue 151 152 # 153 # Matching on source type 154 # 155 if self.source and not match_indirect_regex( 156 rule.source, 157 self.source, 158 self.source_indirect, 159 self.source_regex): 160 continue 161 162 # 163 # Matching on target type 164 # 165 if self.target and not match_indirect_regex( 166 rule.target, 167 self.target, 168 self.target_indirect, 169 self.target_regex): 170 continue 171 172 # 173 # Matching on object class 174 # 175 if not self._match_object_class(rule): 176 continue 177 178 # 179 # Matching on permission set 180 # 181 try: 182 if self.perms and rule.extended: 183 if self.perms_equal and len(self.perms) > 1: 184 # if criteria is more than one standard permission, 185 # extended perm rules can never match if the 186 # permission set equality option is on. 187 continue 188 189 if rule.xperm_type not in self.perms: 190 continue 191 elif not self._match_perms(rule): 192 continue 193 except RuleUseError: 194 continue 195 196 # 197 # Matching on extended permissions 198 # 199 try: 200 if self.xperms and not match_regex_or_set( 201 rule.perms, 202 self.xperms, 203 self.xperms_equal, 204 False): 205 continue 206 207 except RuleUseError: 208 continue 209 210 # 211 # Matching on default type 212 # 213 if self.default: 214 try: 215 # because default type is always a single 216 # type, hard-code indirect to True 217 # so the criteria can be an attribute 218 if not match_indirect_regex( 219 rule.default, 220 self.default, 221 True, 222 self.default_regex): 223 continue 224 except RuleUseError: 225 continue 226 227 # 228 # Match on Boolean in conditional expression 229 # 230 if self.boolean: 231 try: 232 if not match_regex_or_set( 233 rule.conditional.booleans, 234 self.boolean, 235 self.boolean_equal, 236 self.boolean_regex): 237 continue 238 except RuleNotConditional: 239 continue 240 241 # if we get here, we have matched all available criteria 242 yield rule 243