diff options
Diffstat (limited to 'lib/python2.7/site-packages/setools/diff')
27 files changed, 604 insertions, 327 deletions
diff --git a/lib/python2.7/site-packages/setools/diff/__init__.py b/lib/python2.7/site-packages/setools/diff/__init__.py index 8d5900a..612574c 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/__init__.py +++ b/lib/python2.7/site-packages/setools/diff/__init__.py @@ -17,7 +17,9 @@ # <http://www.gnu.org/licenses/>. # from .bool import BooleansDifference +from .bounds import BoundsDifference from .commons import CommonDifference +from .constraints import ConstraintsDifference from .default import DefaultsDifference from .fsuse import FSUsesDifference from .genfscon import GenfsconsDifference @@ -41,8 +43,10 @@ __all__ = ['PolicyDifference'] class PolicyDifference(BooleansDifference, + BoundsDifference, CategoriesDifference, CommonDifference, + ConstraintsDifference, DefaultsDifference, FSUsesDifference, GenfsconsDifference, diff --git a/lib/python2.7/site-packages/setools/diff/bool.py b/lib/python2.7/site-packages/setools/diff/bool.py index 212a715..212a715 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/bool.py +++ b/lib/python2.7/site-packages/setools/diff/bool.py diff --git a/lib/python2.7/site-packages/setools/diff/bounds.py b/lib/python2.7/site-packages/setools/diff/bounds.py new file mode 100755 index 0000000..e23c91f --- /dev/null +++ b/lib/python2.7/site-packages/setools/diff/bounds.py @@ -0,0 +1,112 @@ +# 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 + + +modified_bounds_record = namedtuple("modified_bound", ["rule", "added_bound", "removed_bound"]) + + +class BoundsDifference(Difference): + + """Determine the difference in *bounds between two policies.""" + + added_typebounds = DiffResultDescriptor("diff_typebounds") + removed_typebounds = DiffResultDescriptor("diff_typebounds") + modified_typebounds = DiffResultDescriptor("diff_typebounds") + + # Lists of rules for each policy + _left_typebounds = None + _right_typebounds = None + + def diff_typebounds(self): + """Generate the difference in typebound rules between the policies.""" + + self.log.info("Generating typebounds differences from {0.left_policy} to {0.right_policy}". + format(self)) + + if self._left_typebounds is None or self._right_typebounds is None: + self._create_typebound_lists() + + self.added_typebounds, self.removed_typebounds, matched_typebounds = self._set_diff( + (BoundsWrapper(c) for c in self._left_typebounds), + (BoundsWrapper(c) for c in self._right_typebounds), + key=lambda b: str(b.child)) + + self.modified_typebounds = [] + + for left_bound, right_bound in matched_typebounds: + if SymbolWrapper(left_bound.parent) != SymbolWrapper(right_bound.parent): + self.modified_typebounds.append(modified_bounds_record( + left_bound, right_bound.parent, left_bound.parent)) + + # + # Internal functions + # + def _create_typebound_lists(self): + """Create rule lists for both policies.""" + self._left_typebounds = [] + for rule in self.left_policy.bounds(): + if rule.ruletype == "typebounds": + self._left_typebounds.append(rule) + else: + self.log.error("Unknown rule type: {0} (This is an SETools bug)". + format(rule.ruletype)) + + self._right_typebounds = [] + for rule in self.right_policy.bounds(): + if rule.ruletype == "typebounds": + self._right_typebounds.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 *bounds differences") + self.added_typebounds = None + self.removed_typebounds = None + + # Sets of rules for each policy + self._left_typebounds = None + self._right_typebounds = None + + +class BoundsWrapper(Wrapper): + + """Wrap *bounds for diff purposes.""" + + def __init__(self, rule): + self.origin = rule + self.ruletype = rule.ruletype + self.parent = SymbolWrapper(rule.parent) + self.child = SymbolWrapper(rule.child) + self.key = hash(rule) + + 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.child == other.child diff --git a/lib/python2.7/site-packages/setools/diff/commons.py b/lib/python2.7/site-packages/setools/diff/commons.py index 41c13f8..41c13f8 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/commons.py +++ b/lib/python2.7/site-packages/setools/diff/commons.py diff --git a/lib/python2.7/site-packages/setools/diff/conditional.py b/lib/python2.7/site-packages/setools/diff/conditional.py index 95a620e..95a620e 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/conditional.py +++ b/lib/python2.7/site-packages/setools/diff/conditional.py 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 diff --git a/lib/python2.7/site-packages/setools/diff/context.py b/lib/python2.7/site-packages/setools/diff/context.py index 4124aff..4124aff 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/context.py +++ b/lib/python2.7/site-packages/setools/diff/context.py diff --git a/lib/python2.7/site-packages/setools/diff/default.py b/lib/python2.7/site-packages/setools/diff/default.py index ce7c569..ce7c569 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/default.py +++ b/lib/python2.7/site-packages/setools/diff/default.py diff --git a/lib/python2.7/site-packages/setools/diff/descriptors.py b/lib/python2.7/site-packages/setools/diff/descriptors.py index 2295d74..2295d74 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/descriptors.py +++ b/lib/python2.7/site-packages/setools/diff/descriptors.py diff --git a/lib/python2.7/site-packages/setools/diff/difference.py b/lib/python2.7/site-packages/setools/diff/difference.py index 189c67d..f3cde8a 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/difference.py +++ b/lib/python2.7/site-packages/setools/diff/difference.py @@ -27,7 +27,7 @@ class Difference(object): """Base class for all policy differences.""" def __init__(self, left_policy, right_policy): - self.log = logging.getLogger(self.__class__.__name__) + self.log = logging.getLogger(__name__) self.left_policy = left_policy self.right_policy = right_policy @@ -72,7 +72,7 @@ class Difference(object): yield Wrapper(expanded_rule) @staticmethod - def _set_diff(left, right): + def _set_diff(left, right, key=None): """ Standard diff of two sets. @@ -108,8 +108,8 @@ class Difference(object): # instead of giving wrong results. If there is a better way to, # ensure the items match up, please let me know how or submit a patch. matched_items = set() - left_matched_items = sorted((left_items - removed_items)) - right_matched_items = sorted((right_items - added_items)) + left_matched_items = sorted((left_items - removed_items), key=key) + right_matched_items = sorted((right_items - added_items), key=key) assert len(left_matched_items) == len(right_matched_items), \ "Matched items assertion failure (this is an SETools bug), {0} != {1}". \ format(len(left_matched_items), len(right_matched_items)) diff --git a/lib/python2.7/site-packages/setools/diff/fsuse.py b/lib/python2.7/site-packages/setools/diff/fsuse.py index 3a0c0e1..3a0c0e1 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/fsuse.py +++ b/lib/python2.7/site-packages/setools/diff/fsuse.py diff --git a/lib/python2.7/site-packages/setools/diff/genfscon.py b/lib/python2.7/site-packages/setools/diff/genfscon.py index 24f0a7d..24f0a7d 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/genfscon.py +++ b/lib/python2.7/site-packages/setools/diff/genfscon.py diff --git a/lib/python2.7/site-packages/setools/diff/initsid.py b/lib/python2.7/site-packages/setools/diff/initsid.py index 33098ad..33098ad 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/initsid.py +++ b/lib/python2.7/site-packages/setools/diff/initsid.py diff --git a/lib/python2.7/site-packages/setools/diff/mls.py b/lib/python2.7/site-packages/setools/diff/mls.py index efd758f..efd758f 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/mls.py +++ b/lib/python2.7/site-packages/setools/diff/mls.py diff --git a/lib/python2.7/site-packages/setools/diff/mlsrules.py b/lib/python2.7/site-packages/setools/diff/mlsrules.py index 75f443e..80f99b2 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/mlsrules.py +++ b/lib/python2.7/site-packages/setools/diff/mlsrules.py @@ -16,7 +16,7 @@ # License along with SETools. If not, see # <http://www.gnu.org/licenses/>. # -from collections import namedtuple +from collections import defaultdict, namedtuple from .descriptors import DiffResultDescriptor from .difference import Difference, SymbolWrapper, Wrapper @@ -37,8 +37,8 @@ class MLSRulesDifference(Difference): modified_range_transitions = DiffResultDescriptor("diff_range_transitions") # Lists of rules for each policy - _left_range_transitions = None - _right_range_transitions = None + _left_mls_rules = defaultdict(list) + _right_mls_rules = defaultdict(list) def diff_range_transitions(self): """Generate the difference in range_transition rules between the policies.""" @@ -47,43 +47,12 @@ class MLSRulesDifference(Difference): "Generating range_transition differences from {0.left_policy} to {0.right_policy}". format(self)) - if self._left_range_transitions is None or self._right_range_transitions is None: + if not self._left_mls_rules or not self._right_mls_rules: self._create_mls_rule_lists() - self.added_range_transitions, \ - self.removed_range_transitions, \ - self.modified_range_transitions = self._diff_mls_rules( - self._expand_generator(self._left_range_transitions, MLSRuleWrapper), - self._expand_generator(self._right_range_transitions, MLSRuleWrapper)) - - # - # Internal functions - # - def _create_mls_rule_lists(self): - """Create rule lists for both policies.""" - self._left_range_transitions = [] - for rule in self.left_policy.mlsrules(): - # do not expand yet, to keep memory - # use down as long as possible - if rule.ruletype == "range_transition": - self._left_range_transitions.append(rule) - else: - self.log.error("Unknown rule type: {0} (This is an SETools bug)". - format(rule.ruletype)) - - self._right_range_transitions = [] - for rule in self.right_policy.mlsrules(): - # do not expand yet, to keep memory - # use down as long as possible - if rule.ruletype == "range_transition": - self._right_range_transitions.append(rule) - else: - self.log.error("Unknown rule type: {0} (This is an SETools bug)". - format(rule.ruletype)) - - def _diff_mls_rules(self, left_list, right_list): - """Common method for comparing type_* rules.""" - added, removed, matched = self._set_diff(left_list, right_list) + added, removed, matched = self._set_diff( + self._expand_generator(self._left_mls_rules["range_transition"], MLSRuleWrapper), + self._expand_generator(self._right_mls_rules["range_transition"], MLSRuleWrapper)) modified = [] @@ -95,7 +64,26 @@ class MLSRulesDifference(Difference): right_rule.default, left_rule.default)) - return added, removed, modified + self.added_range_transitions = added + self.removed_range_transitions = removed + self.modified_range_transitions = modified + + # + # Internal functions + # + def _create_mls_rule_lists(self): + """Create rule lists for both policies.""" + # do not expand yet, to keep memory + # use down as long as possible + self.log.debug("Building MLS rule lists from {0.left_policy}".format(self)) + for rule in self.left_policy.mlsrules(): + self._left_mls_rules[rule.ruletype].append(rule) + + self.log.debug("Building MLS rule lists from {0.right_policy}".format(self)) + for rule in self.right_policy.mlsrules(): + self._right_mls_rules[rule.ruletype].append(rule) + + self.log.debug("Completed building MLS rule lists.") def _reset_diff(self): """Reset diff results on policy changes.""" @@ -105,8 +93,8 @@ class MLSRulesDifference(Difference): self.modified_range_transitions = None # Sets of rules for each policy - self._left_range_transitions = None - self._right_range_transitions = None + self._left_mls_rules.clear() + self._right_mls_rules.clear() class MLSRuleWrapper(Wrapper): diff --git a/lib/python2.7/site-packages/setools/diff/netifcon.py b/lib/python2.7/site-packages/setools/diff/netifcon.py index 8a2b9e3..8a2b9e3 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/netifcon.py +++ b/lib/python2.7/site-packages/setools/diff/netifcon.py diff --git a/lib/python2.7/site-packages/setools/diff/nodecon.py b/lib/python2.7/site-packages/setools/diff/nodecon.py index 6e94c9e..6e94c9e 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/nodecon.py +++ b/lib/python2.7/site-packages/setools/diff/nodecon.py diff --git a/lib/python2.7/site-packages/setools/diff/objclass.py b/lib/python2.7/site-packages/setools/diff/objclass.py index 6a12de4..6a12de4 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/objclass.py +++ b/lib/python2.7/site-packages/setools/diff/objclass.py diff --git a/lib/python2.7/site-packages/setools/diff/polcap.py b/lib/python2.7/site-packages/setools/diff/polcap.py index 9c0afe2..9c0afe2 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/polcap.py +++ b/lib/python2.7/site-packages/setools/diff/polcap.py diff --git a/lib/python2.7/site-packages/setools/diff/portcon.py b/lib/python2.7/site-packages/setools/diff/portcon.py index 17df377..17df377 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/portcon.py +++ b/lib/python2.7/site-packages/setools/diff/portcon.py diff --git a/lib/python2.7/site-packages/setools/diff/properties.py b/lib/python2.7/site-packages/setools/diff/properties.py index 8cd4c13..8cd4c13 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/properties.py +++ b/lib/python2.7/site-packages/setools/diff/properties.py diff --git a/lib/python2.7/site-packages/setools/diff/rbacrules.py b/lib/python2.7/site-packages/setools/diff/rbacrules.py index 8a51b88..81be013 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/rbacrules.py +++ b/lib/python2.7/site-packages/setools/diff/rbacrules.py @@ -16,7 +16,7 @@ # License along with SETools. If not, see # <http://www.gnu.org/licenses/>. # -from collections import namedtuple +from collections import defaultdict, namedtuple from .descriptors import DiffResultDescriptor from .difference import Difference, SymbolWrapper, Wrapper @@ -40,11 +40,8 @@ class RBACRulesDifference(Difference): modified_role_transitions = DiffResultDescriptor("diff_role_transitions") # Lists of rules for each policy - _left_role_allows = None - _right_role_allows = None - - _left_role_transitions = None - _right_role_transitions = None + _left_rbac_rules = defaultdict(list) + _right_rbac_rules = defaultdict(list) def diff_role_allows(self): """Generate the difference in role allow rules between the policies.""" @@ -53,12 +50,12 @@ class RBACRulesDifference(Difference): "Generating role allow differences from {0.left_policy} to {0.right_policy}". format(self)) - if self._left_role_allows is None or self._right_role_allows is None: + if not self._left_rbac_rules or not self._right_rbac_rules: self._create_rbac_rule_lists() - self.added_role_allows, self.removed_role_allows, _ = \ - self._set_diff(self._expand_generator(self._left_role_allows, RoleAllowWrapper), - self._expand_generator(self._right_role_allows, RoleAllowWrapper)) + self.added_role_allows, self.removed_role_allows, _ = self._set_diff( + self._expand_generator(self._left_rbac_rules["allow"], RoleAllowWrapper), + self._expand_generator(self._right_rbac_rules["allow"], RoleAllowWrapper)) def diff_role_transitions(self): """Generate the difference in role_transition rules between the policies.""" @@ -67,52 +64,15 @@ class RBACRulesDifference(Difference): "Generating role_transition differences from {0.left_policy} to {0.right_policy}". format(self)) - if self._left_role_transitions is None or self._right_role_transitions is None: + if not self._left_rbac_rules or not self._right_rbac_rules: self._create_rbac_rule_lists() - self.added_role_transitions, \ - self.removed_role_transitions, \ - self.modified_role_transitions = self._diff_rbac_rules( - self._expand_generator(self._left_role_transitions, RoleTransitionWrapper), - self._expand_generator(self._right_role_transitions, RoleTransitionWrapper)) - - # - # Internal functions - # - def _create_rbac_rule_lists(self): - """Create rule lists for both policies.""" - self._left_role_allows = [] - self._left_role_transitions = [] - for rule in self.left_policy.rbacrules(): - # do not expand yet, to keep memory - # use down as long as possible - if rule.ruletype == "allow": - self._left_role_allows.append(rule) - elif rule.ruletype == "role_transition": - self._left_role_transitions.append(rule) - else: - self.log.error("Unknown rule type: {0} (This is an SETools bug)". - format(rule.ruletype)) - - self._right_role_allows = [] - self._right_role_transitions = [] - for rule in self.right_policy.rbacrules(): - # do not expand yet, to keep memory - # use down as long as possible - if rule.ruletype == "allow": - self._right_role_allows.append(rule) - elif rule.ruletype == "role_transition": - self._right_role_transitions.append(rule) - else: - self.log.error("Unknown rule type: {0} (This is an SETools bug)". - format(rule.ruletype)) - - def _diff_rbac_rules(self, left_list, right_list): - """Common method for comparing rbac rules.""" - added, removed, matched = self._set_diff(left_list, right_list) + added, removed, matched = self._set_diff( + self._expand_generator(self._left_rbac_rules["role_transition"], RoleTransitionWrapper), + self._expand_generator(self._right_rbac_rules["role_transition"], + RoleTransitionWrapper)) modified = [] - for left_rule, right_rule in matched: # Criteria for modified rules # 1. change to default role @@ -121,7 +81,26 @@ class RBACRulesDifference(Difference): right_rule.default, left_rule.default)) - return added, removed, modified + self.added_role_transitions = added + self.removed_role_transitions = removed + self.modified_role_transitions = modified + + # + # Internal functions + # + def _create_rbac_rule_lists(self): + """Create rule lists for both policies.""" + # do not expand yet, to keep memory + # use down as long as possible + self.log.debug("Building RBAC rule lists from {0.left_policy}".format(self)) + for rule in self.left_policy.rbacrules(): + self._left_rbac_rules[rule.ruletype].append(rule) + + self.log.debug("Building RBAC rule lists from {0.right_policy}".format(self)) + for rule in self.right_policy.rbacrules(): + self._right_rbac_rules[rule.ruletype].append(rule) + + self.log.debug("Completed building RBAC rule lists.") def _reset_diff(self): """Reset diff results on policy changes.""" @@ -134,10 +113,8 @@ class RBACRulesDifference(Difference): self.modified_role_transitions = None # Sets of rules for each policy - self._left_role_allows = None - self._right_role_allows = None - self._left_role_transitions = None - self._right_role_transitions = None + self._left_rbac_rules.clear() + self._right_rbac_rules.clear() class RoleAllowWrapper(Wrapper): diff --git a/lib/python2.7/site-packages/setools/diff/roles.py b/lib/python2.7/site-packages/setools/diff/roles.py index 38ca84e..38ca84e 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/roles.py +++ b/lib/python2.7/site-packages/setools/diff/roles.py diff --git a/lib/python2.7/site-packages/setools/diff/terules.py b/lib/python2.7/site-packages/setools/diff/terules.py index 179e5ec..437bc06 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/terules.py +++ b/lib/python2.7/site-packages/setools/diff/terules.py @@ -16,8 +16,9 @@ # License along with SETools. If not, see # <http://www.gnu.org/licenses/>. # -from collections import namedtuple +from collections import defaultdict, namedtuple +from ..policyrep import ioctlSet from ..policyrep.exception import RuleNotConditional, RuleUseError, TERuleNoFilename from .conditional import ConditionalExprWrapper @@ -33,272 +34,219 @@ modified_avrule_record = namedtuple("modified_avrule", ["rule", modified_terule_record = namedtuple("modified_terule", ["rule", "added_default", "removed_default"]) -class TERulesDifference(Difference): +def av_diff_template(ruletype): """ - Determine the difference in type enforcement rules - between two policies. - """ + This is a template for the access vector diff functions. - added_allows = DiffResultDescriptor("diff_allows") - removed_allows = DiffResultDescriptor("diff_allows") - modified_allows = DiffResultDescriptor("diff_allows") - - added_auditallows = DiffResultDescriptor("diff_auditallows") - removed_auditallows = DiffResultDescriptor("diff_auditallows") - modified_auditallows = DiffResultDescriptor("diff_auditallows") + Parameters: + ruletype The rule type, e.g. "allow". + """ - added_neverallows = DiffResultDescriptor("diff_neverallows") - removed_neverallows = DiffResultDescriptor("diff_neverallows") - modified_neverallows = DiffResultDescriptor("diff_neverallows") + def diff(self): + """Generate the difference in rules between the policies.""" - added_dontaudits = DiffResultDescriptor("diff_dontaudits") - removed_dontaudits = DiffResultDescriptor("diff_dontaudits") - modified_dontaudits = DiffResultDescriptor("diff_dontaudits") + self.log.info( + "Generating {0} differences from {1.left_policy} to {1.right_policy}". + format(ruletype, self)) - added_type_transitions = DiffResultDescriptor("diff_type_transitions") - removed_type_transitions = DiffResultDescriptor("diff_type_transitions") - modified_type_transitions = DiffResultDescriptor("diff_type_transitions") + if not self._left_te_rules or not self._right_te_rules: + self._create_te_rule_lists() - added_type_changes = DiffResultDescriptor("diff_type_changes") - removed_type_changes = DiffResultDescriptor("diff_type_changes") - modified_type_changes = DiffResultDescriptor("diff_type_changes") + added, removed, matched = self._set_diff( + self._expand_generator(self._left_te_rules[ruletype], AVRuleWrapper), + self._expand_generator(self._right_te_rules[ruletype], AVRuleWrapper)) - added_type_members = DiffResultDescriptor("diff_type_members") - removed_type_members = DiffResultDescriptor("diff_type_members") - modified_type_members = DiffResultDescriptor("diff_type_members") + modified = [] + for left_rule, right_rule in matched: + # Criteria for modified rules + # 1. change to permissions + added_perms, removed_perms, matched_perms = self._set_diff(left_rule.perms, + right_rule.perms) - # Lists of rules for each policy - _left_allows = None - _right_allows = None + # the final set comprehension is to avoid having lists + # like [("perm1", "perm1"), ("perm2", "perm2")], as the + # matched_perms return from _set_diff is a set of tuples + if added_perms or removed_perms: + modified.append(modified_avrule_record(left_rule, + added_perms, + removed_perms, + set(p[0] for p in matched_perms))) - _left_auditallows = None - _right_auditallows = None + setattr(self, "added_{0}s".format(ruletype), added) + setattr(self, "removed_{0}s".format(ruletype), removed) + setattr(self, "modified_{0}s".format(ruletype), modified) - _left_neverallows = None - _right_neverallows = None + return diff - _left_dontaudits = None - _right_dontaudits = None - _left_type_transitions = None - _right_type_transitions = None +def avx_diff_template(ruletype): - _left_type_changes = None - _right_type_changes = None + """ + This is a template for the extended permission access vector diff functions. - _left_type_members = None - _right_type_members = None + Parameters: + ruletype The rule type, e.g. "allowxperm". + """ - def diff_allows(self): - """Generate the difference in allow rules between the policies.""" + def diff(self): + """Generate the difference in rules between the policies.""" self.log.info( - "Generating allow differences from {0.left_policy} to {0.right_policy}".format(self)) + "Generating {0} differences from {1.left_policy} to {1.right_policy}". + format(ruletype, self)) - if self._left_allows is None or self._right_allows is None: + if not self._left_te_rules or not self._right_te_rules: self._create_te_rule_lists() - self.added_allows, self.removed_allows, self.modified_allows = self._diff_av_rules( - self._expand_generator(self._left_allows, AVRuleWrapper), - self._expand_generator(self._right_allows, AVRuleWrapper)) + added, removed, matched = self._set_diff( + self._expand_generator(self._left_te_rules[ruletype], AVRuleXpermWrapper), + self._expand_generator(self._right_te_rules[ruletype], AVRuleXpermWrapper)) - def diff_auditallows(self): - """Generate the difference in auditallow rules between the policies.""" + modified = [] + for left_rule, right_rule in matched: + # Criteria for modified rules + # 1. change to permissions + added_perms, removed_perms, matched_perms = self._set_diff(left_rule.perms, + right_rule.perms) - self.log.info( - "Generating auditallow differences from {0.left_policy} to {0.right_policy}". - format(self)) + # the final set comprehension is to avoid having lists + # like [("perm1", "perm1"), ("perm2", "perm2")], as the + # matched_perms return from _set_diff is a set of tuples + if added_perms or removed_perms: + modified.append(modified_avrule_record(left_rule, + ioctlSet(added_perms), + ioctlSet(removed_perms), + ioctlSet(p[0] for p in matched_perms))) - if self._left_auditallows is None or self._right_auditallows is None: - self._create_te_rule_lists() + setattr(self, "added_{0}s".format(ruletype), added) + setattr(self, "removed_{0}s".format(ruletype), removed) + setattr(self, "modified_{0}s".format(ruletype), modified) - self.added_auditallows, \ - self.removed_auditallows, \ - self.modified_auditallows = self._diff_av_rules( - self._expand_generator(self._left_auditallows, AVRuleWrapper), - self._expand_generator(self._right_auditallows, AVRuleWrapper)) + return diff - def diff_neverallows(self): - """Generate the difference in neverallow rules between the policies.""" - self.log.info( - "Generating neverallow differences from {0.left_policy} to {0.right_policy}". - format(self)) +def te_diff_template(ruletype): - if self._left_neverallows is None or self._right_neverallows is None: - self._create_te_rule_lists() + """ + This is a template for the type_* diff functions. - self.added_neverallows, \ - self.removed_neverallows, \ - self.modified_neverallows = self._diff_av_rules( - self._expand_generator(self._left_neverallows, AVRuleWrapper), - self._expand_generator(self._right_neverallows, AVRuleWrapper)) + Parameters: + ruletype The rule type, e.g. "type_transition". + """ - def diff_dontaudits(self): - """Generate the difference in dontaudit rules between the policies.""" + def diff(self): + """Generate the difference in rules between the policies.""" self.log.info( - "Generating dontaudit differences from {0.left_policy} to {0.right_policy}". - format(self)) + "Generating {0} differences from {1.left_policy} to {1.right_policy}". + format(ruletype, self)) - if self._left_dontaudits is None or self._right_dontaudits is None: + if not self._left_te_rules or not self._right_te_rules: self._create_te_rule_lists() - self.added_dontaudits, \ - self.removed_dontaudits, \ - self.modified_dontaudits = self._diff_av_rules( - self._expand_generator(self._left_dontaudits, AVRuleWrapper), - self._expand_generator(self._right_dontaudits, AVRuleWrapper)) + added, removed, matched = self._set_diff( + self._expand_generator(self._left_te_rules[ruletype], TERuleWrapper), + self._expand_generator(self._right_te_rules[ruletype], TERuleWrapper)) - def diff_type_transitions(self): - """Generate the difference in type_transition rules between the policies.""" - - self.log.info( - "Generating type_transition differences from {0.left_policy} to {0.right_policy}". - format(self)) + modified = [] + for left_rule, right_rule in matched: + # Criteria for modified rules + # 1. change to default type + if SymbolWrapper(left_rule.default) != SymbolWrapper(right_rule.default): + modified.append(modified_terule_record(left_rule, + right_rule.default, + left_rule.default)) - if self._left_type_transitions is None or self._right_type_transitions is None: - self._create_te_rule_lists() + setattr(self, "added_{0}s".format(ruletype), added) + setattr(self, "removed_{0}s".format(ruletype), removed) + setattr(self, "modified_{0}s".format(ruletype), modified) - self.added_type_transitions, \ - self.removed_type_transitions, \ - self.modified_type_transitions = self._diff_te_rules( - self._expand_generator(self._left_type_transitions, TERuleWrapper), - self._expand_generator(self._right_type_transitions, TERuleWrapper)) + return diff - def diff_type_changes(self): - """Generate the difference in type_change rules between the policies.""" - self.log.info( - "Generating type_change differences from {0.left_policy} to {0.right_policy}". - format(self)) +class TERulesDifference(Difference): - if self._left_type_changes is None or self._right_type_changes is None: - self._create_te_rule_lists() + """ + Determine the difference in type enforcement rules + between two policies. + """ - self.added_type_changes, \ - self.removed_type_changes, \ - self.modified_type_changes = self._diff_te_rules( - self._expand_generator(self._left_type_changes, TERuleWrapper), - self._expand_generator(self._right_type_changes, TERuleWrapper)) + diff_allows = av_diff_template("allow") + added_allows = DiffResultDescriptor("diff_allows") + removed_allows = DiffResultDescriptor("diff_allows") + modified_allows = DiffResultDescriptor("diff_allows") - def diff_type_members(self): - """Generate the difference in type_member rules between the policies.""" + diff_auditallows = av_diff_template("auditallow") + added_auditallows = DiffResultDescriptor("diff_auditallows") + removed_auditallows = DiffResultDescriptor("diff_auditallows") + modified_auditallows = DiffResultDescriptor("diff_auditallows") - self.log.info( - "Generating type_member differences from {0.left_policy} to {0.right_policy}". - format(self)) + diff_neverallows = av_diff_template("neverallow") + added_neverallows = DiffResultDescriptor("diff_neverallows") + removed_neverallows = DiffResultDescriptor("diff_neverallows") + modified_neverallows = DiffResultDescriptor("diff_neverallows") - if self._left_type_members is None or self._right_type_members is None: - self._create_te_rule_lists() + diff_dontaudits = av_diff_template("dontaudit") + added_dontaudits = DiffResultDescriptor("diff_dontaudits") + removed_dontaudits = DiffResultDescriptor("diff_dontaudits") + modified_dontaudits = DiffResultDescriptor("diff_dontaudits") - self.added_type_members, \ - self.removed_type_members, \ - self.modified_type_members = self._diff_te_rules( - self._expand_generator(self._left_type_members, TERuleWrapper), - self._expand_generator(self._right_type_members, TERuleWrapper)) + diff_allowxperms = avx_diff_template("allowxperm") + added_allowxperms = DiffResultDescriptor("diff_allowxperms") + removed_allowxperms = DiffResultDescriptor("diff_allowxperms") + modified_allowxperms = DiffResultDescriptor("diff_allowxperms") - # - # Internal functions - # - def _create_te_rule_lists(self): - """Create rule lists for both policies.""" + diff_auditallowxperms = avx_diff_template("auditallowxperm") + added_auditallowxperms = DiffResultDescriptor("diff_auditallowxperms") + removed_auditallowxperms = DiffResultDescriptor("diff_auditallowxperms") + modified_auditallowxperms = DiffResultDescriptor("diff_auditallowxperms") - self._left_allows = [] - self._left_auditallows = [] - self._left_neverallows = [] - self._left_dontaudits = [] - self._left_type_transitions = [] - self._left_type_changes = [] - self._left_type_members = [] - for rule in self.left_policy.terules(): - # do not expand yet, to keep memory - # use down as long as possible - if rule.ruletype == "allow": - self._left_allows.append(rule) - elif rule.ruletype == "auditallow": - self._left_auditallows.append(rule) - elif rule.ruletype == "neverallow": - self._left_neverallows.append(rule) - elif rule.ruletype == "dontaudit": - self._left_dontaudits.append(rule) - elif rule.ruletype == "type_transition": - self._left_type_transitions.append(rule) - elif rule.ruletype == "type_change": - self._left_type_changes.append(rule) - elif rule.ruletype == "type_member": - self._left_type_members.append(rule) - else: - self.log.error("Unknown rule type: {0} (This is an SETools bug)". - format(rule.ruletype)) - - self._right_allows = [] - self._right_auditallows = [] - self._right_neverallows = [] - self._right_dontaudits = [] - self._right_type_transitions = [] - self._right_type_changes = [] - self._right_type_members = [] - for rule in self.right_policy.terules(): - # do not expand yet, to keep memory - # use down as long as possible - if rule.ruletype == "allow": - self._right_allows.append(rule) - elif rule.ruletype == "auditallow": - self._right_auditallows.append(rule) - elif rule.ruletype == "neverallow": - self._right_neverallows.append(rule) - elif rule.ruletype == "dontaudit": - self._right_dontaudits.append(rule) - elif rule.ruletype == "type_transition": - self._right_type_transitions.append(rule) - elif rule.ruletype == "type_change": - self._right_type_changes.append(rule) - elif rule.ruletype == "type_member": - self._right_type_members.append(rule) - else: - self.log.error("Unknown rule type: {0} (This is an SETools bug)". - format(rule.ruletype)) - - def _diff_av_rules(self, left_list, right_list): - """Common method for comparing access vector rules.""" - added, removed, matched = self._set_diff(left_list, right_list) + diff_neverallowxperms = avx_diff_template("neverallowxperm") + added_neverallowxperms = DiffResultDescriptor("diff_neverallowxperms") + removed_neverallowxperms = DiffResultDescriptor("diff_neverallowxperms") + modified_neverallowxperms = DiffResultDescriptor("diff_neverallowxperms") - modified = [] + diff_dontauditxperms = avx_diff_template("dontauditxperm") + added_dontauditxperms = DiffResultDescriptor("diff_dontauditxperms") + removed_dontauditxperms = DiffResultDescriptor("diff_dontauditxperms") + modified_dontauditxperms = DiffResultDescriptor("diff_dontauditxperms") - for left_rule, right_rule in matched: - # Criteria for modified rules - # 1. change to permissions - added_perms, removed_perms, matched_perms = self._set_diff(left_rule.perms, - right_rule.perms) + diff_type_transitions = te_diff_template("type_transition") + added_type_transitions = DiffResultDescriptor("diff_type_transitions") + removed_type_transitions = DiffResultDescriptor("diff_type_transitions") + modified_type_transitions = DiffResultDescriptor("diff_type_transitions") - # the final set comprehension is to avoid having lists - # like [("perm1", "perm1"), ("perm2", "perm2")], as the - # matched_perms return from _set_diff is a set of tuples - if added_perms or removed_perms: - modified.append(modified_avrule_record(left_rule, - added_perms, - removed_perms, - set(p[0] for p in matched_perms))) + diff_type_changes = te_diff_template("type_change") + added_type_changes = DiffResultDescriptor("diff_type_changes") + removed_type_changes = DiffResultDescriptor("diff_type_changes") + modified_type_changes = DiffResultDescriptor("diff_type_changes") - return added, removed, modified + diff_type_members = te_diff_template("type_member") + added_type_members = DiffResultDescriptor("diff_type_members") + removed_type_members = DiffResultDescriptor("diff_type_members") + modified_type_members = DiffResultDescriptor("diff_type_members") - def _diff_te_rules(self, left_list, right_list): - """Common method for comparing type_* rules.""" - added, removed, matched = self._set_diff(left_list, right_list) + # Lists of rules for each policy + _left_te_rules = defaultdict(list) + _right_te_rules = defaultdict(list) - modified = [] + # + # Internal functions + # + def _create_te_rule_lists(self): + """Create rule lists for both policies.""" + # do not expand yet, to keep memory + # use down as long as possible + self.log.debug("Building TE rule lists from {0.left_policy}".format(self)) + for rule in self.left_policy.terules(): + self._left_te_rules[rule.ruletype].append(rule) - for left_rule, right_rule in matched: - # Criteria for modified rules - # 1. change to default type - if SymbolWrapper(left_rule.default) != SymbolWrapper(right_rule.default): - modified.append(modified_terule_record(left_rule, - right_rule.default, - left_rule.default)) + self.log.debug("Building TE rule lists from {0.right_policy}".format(self)) + for rule in self.right_policy.terules(): + self._right_te_rules[rule.ruletype].append(rule) - return added, removed, modified + self.log.debug("Completed building TE rule lists.") def _reset_diff(self): """Reset diff results on policy changes.""" @@ -315,6 +263,18 @@ class TERulesDifference(Difference): self.added_dontaudits = None self.removed_dontaudits = None self.modified_dontaudits = None + self.added_allowxperms = None + self.removed_allowxperms = None + self.modified_allowxperms = None + self.added_auditallowxperms = None + self.removed_auditallowxperms = None + self.modified_auditallowxperms = None + self.added_neverallowxperms = None + self.removed_neverallowxperms = None + self.modified_neverallowxperms = None + self.added_dontauditxperms = None + self.removed_dontauditxperms = None + self.modified_dontauditxperms = None self.added_type_transitions = None self.removed_type_transitions = None self.modified_type_transitions = None @@ -326,20 +286,8 @@ class TERulesDifference(Difference): self.modified_type_members = None # Sets of rules for each policy - self._left_allows = None - self._right_allows = None - self._left_auditallows = None - self._right_auditallows = None - self._left_neverallows = None - self._right_neverallows = None - self._left_dontaudits = None - self._right_dontaudits = None - self._left_type_transitions = None - self._right_type_transitions = None - self._left_type_changes = None - self._right_type_changes = None - self._left_type_members = None - self._right_type_members = None + self._left_te_rules.clear() + self._right_te_rules.clear() class AVRuleWrapper(Wrapper): @@ -377,6 +325,34 @@ class AVRuleWrapper(Wrapper): self.conditional_block == other.conditional_block +class AVRuleXpermWrapper(Wrapper): + + """Wrap extended permission access vector rules to allow set operations.""" + + def __init__(self, rule): + self.origin = rule + self.ruletype = rule.ruletype + self.source = SymbolWrapper(rule.source) + self.target = SymbolWrapper(rule.target) + self.tclass = SymbolWrapper(rule.tclass) + self.xperm_type = rule.xperm_type + self.key = hash(rule) + + def __hash__(self): + return self.key + + def __lt__(self, other): + return self.key < other.key + + def __eq__(self, other): + # because TERuleDifference groups rules by ruletype, + # the ruletype always matches. + return self.source == other.source and \ + self.target == other.target and \ + self.tclass == other.tclass and \ + self.xperm_type == other.xperm_type + + class TERuleWrapper(Wrapper): """Wrap type_* rules to allow set operations.""" diff --git a/lib/python2.7/site-packages/setools/diff/typeattr.py b/lib/python2.7/site-packages/setools/diff/typeattr.py index 8c51832..8c51832 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/typeattr.py +++ b/lib/python2.7/site-packages/setools/diff/typeattr.py diff --git a/lib/python2.7/site-packages/setools/diff/types.py b/lib/python2.7/site-packages/setools/diff/types.py index d0e99d9..d0e99d9 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/types.py +++ b/lib/python2.7/site-packages/setools/diff/types.py diff --git a/lib/python2.7/site-packages/setools/diff/users.py b/lib/python2.7/site-packages/setools/diff/users.py index 78f3d3e..78f3d3e 100644..100755 --- a/lib/python2.7/site-packages/setools/diff/users.py +++ b/lib/python2.7/site-packages/setools/diff/users.py |