Home | History | Annotate | Download | only in diff
      1 # Copyright 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 collections import namedtuple
     20 
     21 from .context import ContextWrapper
     22 from .descriptors import DiffResultDescriptor
     23 from .difference import Difference, Wrapper
     24 
     25 
     26 modified_genfs_record = namedtuple("modified_genfs", ["rule",
     27                                                       "added_context",
     28                                                       "removed_context"])
     29 
     30 
     31 class GenfsconsDifference(Difference):
     32 
     33     """Determine the difference in genfscon rules between two policies."""
     34 
     35     added_genfscons = DiffResultDescriptor("diff_genfscons")
     36     removed_genfscons = DiffResultDescriptor("diff_genfscons")
     37     modified_genfscons = DiffResultDescriptor("diff_genfscons")
     38 
     39     def diff_genfscons(self):
     40         """Generate the difference in genfscon rules between the policies."""
     41 
     42         self.log.info(
     43             "Generating genfscon differences from {0.left_policy} to {0.right_policy}".
     44             format(self))
     45 
     46         self.added_genfscons, self.removed_genfscons, matched = self._set_diff(
     47             (GenfsconWrapper(fs) for fs in self.left_policy.genfscons()),
     48             (GenfsconWrapper(fs) for fs in self.right_policy.genfscons()))
     49 
     50         self.modified_genfscons = []
     51 
     52         for left_rule, right_rule in matched:
     53             # Criteria for modified rules
     54             # 1. change to context
     55             if ContextWrapper(left_rule.context) != ContextWrapper(right_rule.context):
     56                 self.modified_genfscons.append(modified_genfs_record(left_rule,
     57                                                                      right_rule.context,
     58                                                                      left_rule.context))
     59 
     60     #
     61     # Internal functions
     62     #
     63     def _reset_diff(self):
     64         """Reset diff results on policy changes."""
     65         self.log.debug("Resetting genfscon rule differences")
     66         self.added_genfscons = None
     67         self.removed_genfscons = None
     68         self.modified_genfscons = None
     69 
     70 
     71 class GenfsconWrapper(Wrapper):
     72 
     73     """Wrap genfscon rules to allow set operations."""
     74 
     75     def __init__(self, rule):
     76         self.origin = rule
     77         self.fs = rule.fs
     78         self.path = rule.path
     79         self.filetype = rule.filetype
     80         self.context = ContextWrapper(rule.context)
     81         self.key = hash(rule)
     82 
     83     def __hash__(self):
     84         return self.key
     85 
     86     def __lt__(self, other):
     87         return self.key < other.key
     88 
     89     def __eq__(self, other):
     90         return self.fs == other.fs and \
     91                self.path == other.path and \
     92                self.filetype == other.filetype
     93