diff options
Diffstat (limited to 'lib/python2.7/site-packages/setools/diff/constraints.py')
-rwxr-xr-x | lib/python2.7/site-packages/setools/diff/constraints.py | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/lib/python2.7/site-packages/setools/diff/constraints.py b/lib/python2.7/site-packages/setools/diff/constraints.py new file mode 100755 index 0000000..d2e50f4 --- /dev/null +++ b/lib/python2.7/site-packages/setools/diff/constraints.py @@ -0,0 +1,220 @@ +# Copyright 2016, Tresys Technology, LLC +# +# This file is part of SETools. +# +# SETools is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 2.1 of +# the License, or (at your option) any later version. +# +# SETools is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with SETools. If not, see +# <http://www.gnu.org/licenses/>. +# +from collections import namedtuple + +from .descriptors import DiffResultDescriptor +from .difference import Difference, SymbolWrapper, Wrapper + + +class ConstraintsDifference(Difference): + + """ + Determine the difference in constraints between two policies. + + Since the compiler does not union constraints, there may be multiple + constraints with the same ruletype, object class, and permission + set, so constraints can only be added or removed, not modified. + + The constraint expressions are compared only on a basic level. + Expressions that are logically equivalent but are structurally + different, for example, by associativity, will be considered + different. Type and role attributes are also not expanded, + so if there are changes to attribute members, it will not + be reflected as a difference. + """ + + added_constrains = DiffResultDescriptor("diff_constrains") + removed_constrains = DiffResultDescriptor("diff_constrains") + + added_mlsconstrains = DiffResultDescriptor("diff_mlsconstrains") + removed_mlsconstrains = DiffResultDescriptor("diff_mlsconstrains") + + added_validatetrans = DiffResultDescriptor("diff_validatetrans") + removed_validatetrans = DiffResultDescriptor("diff_validatetrans") + + added_mlsvalidatetrans = DiffResultDescriptor("diff_mlsvalidatetrans") + removed_mlsvalidatetrans = DiffResultDescriptor("diff_mlsvalidatetrans") + + # Lists of rules for each policy + _left_constrains = None + _right_constrains = None + + _left_mlsconstrains = None + _right_mlsconstrains = None + + _left_validatetrans = None + _right_validatetrans = None + + _left_mlsvalidatetrans = None + _right_mlsvalidatetrans = None + + def diff_constrains(self): + """Generate the difference in constraint rules between the policies.""" + + self.log.info("Generating constraint differences from {0.left_policy} to {0.right_policy}". + format(self)) + + if self._left_constrains is None or self._right_constrains is None: + self._create_constrain_lists() + + self.added_constrains, self.removed_constrains, _ = self._set_diff( + (ConstraintWrapper(c) for c in self._left_constrains), + (ConstraintWrapper(c) for c in self._right_constrains)) + + def diff_mlsconstrains(self): + """Generate the difference in MLS constraint rules between the policies.""" + + self.log.info( + "Generating MLS constraint differences from {0.left_policy} to {0.right_policy}". + format(self)) + + if self._left_mlsconstrains is None or self._right_mlsconstrains is None: + self._create_constrain_lists() + + self.added_mlsconstrains, self.removed_mlsconstrains, _ = self._set_diff( + (ConstraintWrapper(c) for c in self._left_mlsconstrains), + (ConstraintWrapper(c) for c in self._right_mlsconstrains)) + + def diff_validatetrans(self): + """Generate the difference in validatetrans rules between the policies.""" + + self.log.info( + "Generating validatetrans differences from {0.left_policy} to {0.right_policy}". + format(self)) + + if self._left_validatetrans is None or self._right_validatetrans is None: + self._create_constrain_lists() + + self.added_validatetrans, self.removed_validatetrans, _ = self._set_diff( + (ConstraintWrapper(c) for c in self._left_validatetrans), + (ConstraintWrapper(c) for c in self._right_validatetrans)) + + def diff_mlsvalidatetrans(self): + """Generate the difference in MLS validatetrans rules between the policies.""" + + self.log.info( + "Generating mlsvalidatetrans differences from {0.left_policy} to {0.right_policy}". + format(self)) + + if self._left_mlsvalidatetrans is None or self._right_mlsvalidatetrans is None: + self._create_constrain_lists() + + self.added_mlsvalidatetrans, self.removed_mlsvalidatetrans, _ = self._set_diff( + (ConstraintWrapper(c) for c in self._left_mlsvalidatetrans), + (ConstraintWrapper(c) for c in self._right_mlsvalidatetrans)) + + # + # Internal functions + # + def _create_constrain_lists(self): + """Create rule lists for both policies.""" + self._left_constrains = [] + self._left_mlsconstrains = [] + self._left_validatetrans = [] + self._left_mlsvalidatetrans = [] + for rule in self.left_policy.constraints(): + if rule.ruletype == "constrain": + self._left_constrains.append(rule) + elif rule.ruletype == "mlsconstrain": + self._left_mlsconstrains.append(rule) + elif rule.ruletype == "validatetrans": + self._left_validatetrans.append(rule) + elif rule.ruletype == "mlsvalidatetrans": + self._left_mlsvalidatetrans.append(rule) + else: + self.log.error("Unknown rule type: {0} (This is an SETools bug)". + format(rule.ruletype)) + + self._right_constrains = [] + self._right_mlsconstrains = [] + self._right_validatetrans = [] + self._right_mlsvalidatetrans = [] + for rule in self.right_policy.constraints(): + if rule.ruletype == "constrain": + self._right_constrains.append(rule) + elif rule.ruletype == "mlsconstrain": + self._right_mlsconstrains.append(rule) + elif rule.ruletype == "validatetrans": + self._right_validatetrans.append(rule) + elif rule.ruletype == "mlsvalidatetrans": + self._right_mlsvalidatetrans.append(rule) + else: + self.log.error("Unknown rule type: {0} (This is an SETools bug)". + format(rule.ruletype)) + + def _reset_diff(self): + """Reset diff results on policy changes.""" + self.log.debug("Resetting all constraints differences") + self.added_constrains = None + self.removed_constrains = None + self.added_mlsconstrains = None + self.removed_mlsconstrains = None + self.added_validatetrans = None + self.removed_validatetrans = None + self.added_mlsvalidatetrans = None + self.removed_mlsvalidatetrans = None + + # Sets of rules for each policy + self._left_constrains = None + self._left_mlsconstrains = None + self._left_validatetrans = None + self._left_mlsvalidatetrans = None + self._right_constrains = None + self._right_mlsconstrains = None + self._right_validatetrans = None + self._right_mlsvalidatetrans = None + + +class ConstraintWrapper(Wrapper): + + """Wrap constraints for diff purposes.""" + + def __init__(self, rule): + self.origin = rule + self.ruletype = rule.ruletype + self.tclass = SymbolWrapper(rule.tclass) + + try: + self.perms = rule.perms + except AttributeError: + # (mls)validatetrans + self.perms = None + + self.key = hash(rule) + + self.expr = [] + for op in rule.postfix_expression(): + if isinstance(op, frozenset): + # lists of types/users/roles + self.expr.append(frozenset(SymbolWrapper(item) for item in op)) + else: + # strings in the expression such as u1/r1/t1 or "==" + self.expr.append(op) + + def __hash__(self): + return self.key + + def __lt__(self, other): + return self.key < other.key + + def __eq__(self, other): + return self.ruletype == other.ruletype and \ + self.tclass == other.tclass and \ + self.perms == other.perms and \ + self.expr == other.expr |