Home | History | Annotate | Download | only in diff
      1 # Copyright 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 from collections import namedtuple
     20 
     21 from ..policyrep.exception import NoCommon
     22 
     23 from .descriptors import DiffResultDescriptor
     24 from .difference import Difference, SymbolWrapper
     25 
     26 
     27 modified_classes_record = namedtuple("modified_class", ["added_perms",
     28                                                         "removed_perms",
     29                                                         "matched_perms"])
     30 
     31 
     32 class ObjClassDifference(Difference):
     33 
     34     """
     35     Determine the difference in object classes
     36     between two policies.
     37     """
     38 
     39     added_classes = DiffResultDescriptor("diff_classes")
     40     removed_classes = DiffResultDescriptor("diff_classes")
     41     modified_classes = DiffResultDescriptor("diff_classes")
     42 
     43     def diff_classes(self):
     44         """Generate the difference in object classes between the policies."""
     45 
     46         self.log.info(
     47             "Generating class differences from {0.left_policy} to {0.right_policy}".format(self))
     48 
     49         self.added_classes, self.removed_classes, matched_classes = self._set_diff(
     50             (SymbolWrapper(c) for c in self.left_policy.classes()),
     51             (SymbolWrapper(c) for c in self.right_policy.classes()))
     52 
     53         self.modified_classes = dict()
     54 
     55         for left_class, right_class in matched_classes:
     56             # Criteria for modified classes
     57             # 1. change to permissions (inherited common is expanded)
     58 
     59             left_perms = left_class.perms
     60             try:
     61                 left_perms |= left_class.common.perms
     62             except NoCommon:
     63                 pass
     64 
     65             right_perms = right_class.perms
     66             try:
     67                 right_perms |= right_class.common.perms
     68             except NoCommon:
     69                 pass
     70 
     71             added_perms, removed_perms, matched_perms = self._set_diff(left_perms, right_perms)
     72 
     73             if added_perms or removed_perms:
     74                 self.modified_classes[left_class] = modified_classes_record(added_perms,
     75                                                                             removed_perms,
     76                                                                             matched_perms)
     77 
     78     #
     79     # Internal functions
     80     #
     81     def _reset_diff(self):
     82         """Reset diff results on policy changes."""
     83         self.log.debug("Resetting object class differences")
     84         self.added_classes = None
     85         self.removed_classes = None
     86         self.modified_classes = None
     87