PolicyDifference: implement netifcon diff

Closes #39
This commit is contained in:
Chris PeBenito 2016-01-14 17:51:34 -05:00
parent 0c1b0a101d
commit 485c9746b4
6 changed files with 216 additions and 0 deletions

40
sediff
View File

@ -840,6 +840,46 @@ try:
print()
if all_differences or args.netifcon:
if diff.added_netifcons or diff.removed_netifcons or \
diff.modified_netifcons or args.netifcon:
print("Netifcons ({0} Added, {1} Removed, {2} Modified)".format(
len(diff.added_netifcons), len(diff.removed_netifcons),
len(diff.modified_netifcons)))
if diff.added_netifcons and not args.stats:
print(" Added Netifcons: {0}".format(len(diff.added_netifcons)))
for n in sorted(diff.added_netifcons):
print(" + {0}".format(n))
if diff.removed_netifcons and not args.stats:
print(" Removed Netifcons: {0}".format(len(diff.removed_netifcons)))
for n in sorted(diff.removed_netifcons):
print(" - {0}".format(n))
if diff.modified_netifcons and not args.stats:
print(" Modified Netifcons: {0}".format(len(diff.modified_netifcons)))
for entry in sorted(diff.modified_netifcons):
# This output is different than other statements because
# it becomes difficult to read if this was condensed
# into a single line, especially if both contexts
# are modified.
change = []
if entry.removed_context:
change.append("Modified Context")
if entry.removed_packet:
change.append("Modified Packet Context")
print(" * {0.netif} ({1})".format(entry.rule, ", ".join(change)))
if entry.removed_context:
print(" Context:")
print(" + {0}".format(entry.added_context))
print(" - {0}".format(entry.removed_context))
if entry.removed_packet:
print(" Packet Context:")
print(" + {0}".format(entry.added_packet))
print(" - {0}".format(entry.removed_packet))
print()
except Exception as err:
if args.debug:
import traceback

View File

@ -23,6 +23,7 @@ from .genfscon import GenfsconsDifference
from .initsid import InitialSIDsDifference
from .mls import CategoriesDifference, LevelDeclsDifference, SensitivitiesDifference
from .mlsrules import MLSRulesDifference
from .netifcon import NetifconsDifference
from .objclass import ObjClassDifference
from .rbacrules import RBACRulesDifference
from .roles import RolesDifference
@ -42,6 +43,7 @@ class PolicyDifference(BooleansDifference,
InitialSIDsDifference,
LevelDeclsDifference,
MLSRulesDifference,
NetifconsDifference,
ObjClassDifference,
RBACRulesDifference,
RolesDifference,

102
setools/diff/netifcon.py Normal file
View File

@ -0,0 +1,102 @@
# 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 .context import ContextWrapper
from .descriptors import DiffResultDescriptor
from .difference import Difference, Wrapper
modified_netifcon_record = namedtuple("modified_netifcon", ["rule",
"added_context",
"removed_context",
"added_packet",
"removed_packet"])
class NetifconsDifference(Difference):
"""Determine the difference in netifcons between two policies."""
added_netifcons = DiffResultDescriptor("diff_netifcons")
removed_netifcons = DiffResultDescriptor("diff_netifcons")
modified_netifcons = DiffResultDescriptor("diff_netifcons")
def diff_netifcons(self):
"""Generate the difference in netifcons between the policies."""
self.log.info("Generating netifcon differences from {0.left_policy} to {0.right_policy}".
format(self))
self.added_netifcons, self.removed_netifcons, matched_netifcons = self._set_diff(
(NetifconWrapper(n) for n in self.left_policy.netifcons()),
(NetifconWrapper(n) for n in self.right_policy.netifcons()))
self.modified_netifcons = []
for left_netifcon, right_netifcon in matched_netifcons:
# Criteria for modified netifcons
# 1. change to context
# 2. change to packet context
if ContextWrapper(left_netifcon.context) != ContextWrapper(right_netifcon.context):
removed_context = left_netifcon.context
added_context = right_netifcon.context
else:
removed_context = None
added_context = None
if ContextWrapper(left_netifcon.packet) != ContextWrapper(right_netifcon.packet):
removed_packet = left_netifcon.packet
added_packet = right_netifcon.packet
else:
removed_packet = None
added_packet = None
if removed_context or removed_packet:
self.modified_netifcons.append(modified_netifcon_record(
left_netifcon, added_context, removed_context, added_packet, removed_packet))
#
# Internal functions
#
def _reset_diff(self):
"""Reset diff results on policy changes."""
self.log.debug("Resetting netifcon differences")
self.added_netifcons = None
self.removed_netifcons = None
self.modified_netifcons = None
class NetifconWrapper(Wrapper):
"""Wrap netifcon statements for diff purposes."""
def __init__(self, ocon):
self.origin = ocon
self.netif = ocon.netif
self.key = hash(ocon)
def __hash__(self):
return self.key
def __lt__(self, other):
return self.netif < other.netif
def __eq__(self, other):
return self.netif == other.netif

View File

@ -1101,6 +1101,58 @@ class PolicyDifferenceTest(ValidateRule, unittest.TestCase):
self.assertFalse(level.added_categories)
self.assertSetEqual(set(["c4"]), level.removed_categories)
#
# netifcon
#
def test_added_netifcons(self):
"""Diff: added netifcons."""
l = sorted(self.diff.added_netifcons)
self.assertEqual(1, len(l))
rule = l[0]
self.assertEqual("added_netif", rule.netif)
self.assertEqual("system:object_r:system:s0", rule.context)
self.assertEqual("system:object_r:system:s0", rule.packet)
def test_removed_netifcons(self):
"""Diff: removed netifcons."""
l = sorted(self.diff.removed_netifcons)
self.assertEqual(1, len(l))
rule = l[0]
self.assertEqual("removed_netif", rule.netif)
self.assertEqual("system:object_r:system:s0", rule.context)
self.assertEqual("system:object_r:system:s0", rule.packet)
def test_modified_netifcons(self):
"""Diff: modified netifcons."""
l = sorted(self.diff.modified_netifcons)
self.assertEqual(3, len(l))
# modified both contexts
rule, added_context, removed_context, added_packet, removed_packet = l[0]
self.assertEqual("mod_both_netif", rule.netif)
self.assertEqual("added_user:object_r:system:s0", added_context)
self.assertEqual("removed_user:object_r:system:s0", removed_context)
self.assertEqual("added_user:object_r:system:s0", added_packet)
self.assertEqual("removed_user:object_r:system:s0", removed_packet)
# modified context
rule, added_context, removed_context, added_packet, removed_packet = l[1]
self.assertEqual("mod_ctx_netif", rule.netif)
self.assertEqual("added_user:object_r:system:s0", added_context)
self.assertEqual("removed_user:object_r:system:s0", removed_context)
self.assertFalse(added_packet)
self.assertFalse(removed_packet)
# modified packet context
rule, added_context, removed_context, added_packet, removed_packet = l[2]
self.assertEqual("mod_pkt_netif", rule.netif)
self.assertFalse(added_context)
self.assertFalse(removed_context)
self.assertEqual("added_user:object_r:system:s0", added_packet)
self.assertEqual("removed_user:object_r:system:s0", removed_packet)
class PolicyDifferenceTestNoDiff(unittest.TestCase):
@ -1385,3 +1437,15 @@ class PolicyDifferenceTestNoDiff(unittest.TestCase):
def test_modified_levels(self):
"""NoDiff: no modified levels."""
self.assertFalse(self.diff.modified_levels)
def test_added_netifcons(self):
"""NoDiff: no added netifcons."""
self.assertFalse(self.diff.added_netifcons)
def test_removed_netifcons(self):
"""NoDiff: no removed netifcons."""
self.assertFalse(self.diff.removed_netifcons)
def test_modified_netifcons(self):
"""NoDiff: no modified netifcons."""
self.assertFalse(self.diff.modified_netifcons)

View File

@ -633,6 +633,10 @@ genfscon modified_genfs / -s removed_user:object_r:system:s0
portcon tcp 80 system:object_r:system:s0
netifcon eth0 system:object_r:system:s0 system:object_r:system:s0
netifcon removed_netif system:object_r:system:s0 system:object_r:system:s0
netifcon mod_ctx_netif removed_user:object_r:system:s0 system:object_r:system:s0
netifcon mod_pkt_netif system:object_r:system:s0 removed_user:object_r:system:s0
netifcon mod_both_netif removed_user:object_r:system:s0 removed_user:object_r:system:s0
nodecon 127.0.0.1 255.255.255.255 system:object_r:system:s0
nodecon ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system:object_r:system:s0

View File

@ -633,6 +633,10 @@ genfscon modified_genfs / -s added_user:object_r:system:s0
portcon tcp 80 system:object_r:system:s0
netifcon eth0 system:object_r:system:s0 system:object_r:system:s0
netifcon added_netif system:object_r:system:s0 system:object_r:system:s0
netifcon mod_ctx_netif added_user:object_r:system:s0 system:object_r:system:s0
netifcon mod_pkt_netif system:object_r:system:s0 added_user:object_r:system:s0
netifcon mod_both_netif added_user:object_r:system:s0 added_user:object_r:system:s0
nodecon 127.0.0.1 255.255.255.255 system:object_r:system:s0
nodecon ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system:object_r:system:s0