PolicyDifference: implement portcon diff

Closes #37
This commit is contained in:
Chris PeBenito 2016-01-21 10:00:55 -05:00
parent 8c2ea911c6
commit 69df208ab6
6 changed files with 199 additions and 0 deletions

27
sediff
View File

@ -905,6 +905,33 @@ try:
print() print()
if all_differences or args.portcon:
if diff.added_portcons or diff.removed_portcons or diff.modified_portcons \
or args.portcon:
print("Portcons ({0} Added, {1} Removed, {2} Modified)".format(
len(diff.added_portcons), len(diff.removed_portcons),
len(diff.modified_portcons)))
if diff.added_portcons and not args.stats:
print(" Added Portcons: {0}".format(len(diff.added_portcons)))
for n in sorted(diff.added_portcons):
print(" + {0}".format(n))
if diff.removed_portcons and not args.stats:
print(" Removed Portcons: {0}".format(len(diff.removed_portcons)))
for n in sorted(diff.removed_portcons):
print(" - {0}".format(n))
if diff.modified_portcons and not args.stats:
print(" Modified Portcons: {0}".format(len(diff.modified_portcons)))
for con, added_context, removed_context in sorted(diff.modified_portcons):
low, high = con.ports
if low == high:
print(" * portcon {0.protocol} {1} +[{2}] -[{3}];".format(
con, low, added_context, removed_context))
else:
print(" * portcon {0.protocol} {1}-{2} +[{3}] -[{4}];".format(
con, low, high, added_context, removed_context))
print()
if all_differences or args.polcap: if all_differences or args.polcap:
if diff.added_polcaps or diff.removed_polcaps or args.polcap: if diff.added_polcaps or diff.removed_polcaps or args.polcap:
print("Policy Capabilities ({0} Added, {1} Removed)".format( print("Policy Capabilities ({0} Added, {1} Removed)".format(

View File

@ -27,6 +27,7 @@ from .netifcon import NetifconsDifference
from .nodecon import NodeconsDifference from .nodecon import NodeconsDifference
from .objclass import ObjClassDifference from .objclass import ObjClassDifference
from .polcap import PolCapsDifference from .polcap import PolCapsDifference
from .portcon import PortconsDifference
from .rbacrules import RBACRulesDifference from .rbacrules import RBACRulesDifference
from .roles import RolesDifference from .roles import RolesDifference
from .terules import TERulesDifference from .terules import TERulesDifference
@ -49,6 +50,7 @@ class PolicyDifference(BooleansDifference,
NodeconsDifference, NodeconsDifference,
ObjClassDifference, ObjClassDifference,
PolCapsDifference, PolCapsDifference,
PortconsDifference,
RBACRulesDifference, RBACRulesDifference,
RolesDifference, RolesDifference,
SensitivitiesDifference, SensitivitiesDifference,

89
setools/diff/portcon.py Normal file
View File

@ -0,0 +1,89 @@
# 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_portcon_record = namedtuple("modified_portcon", ["rule",
"added_context",
"removed_context"])
class PortconsDifference(Difference):
"""Determine the difference in portcons between two policies."""
added_portcons = DiffResultDescriptor("diff_portcons")
removed_portcons = DiffResultDescriptor("diff_portcons")
modified_portcons = DiffResultDescriptor("diff_portcons")
def diff_portcons(self):
"""Generate the difference in portcons between the policies."""
self.log.info("Generating portcon differences from {0.left_policy} to {0.right_policy}".
format(self))
self.added_portcons, self.removed_portcons, matched_portcons = self._set_diff(
(PortconWrapper(n) for n in self.left_policy.portcons()),
(PortconWrapper(n) for n in self.right_policy.portcons()))
self.modified_portcons = []
for left_portcon, right_portcon in matched_portcons:
# Criteria for modified portcons
# 1. change to context
if ContextWrapper(left_portcon.context) != ContextWrapper(right_portcon.context):
self.modified_portcons.append(modified_portcon_record(left_portcon,
right_portcon.context,
left_portcon.context))
#
# Internal functions
#
def _reset_diff(self):
"""Reset diff results on policy changes."""
self.log.debug("Resetting portcon differences")
self.added_portcons = None
self.removed_portcons = None
self.modified_portcons = None
class PortconWrapper(Wrapper):
"""Wrap portcon statements for diff purposes."""
def __init__(self, ocon):
self.origin = ocon
self.protocol = ocon.protocol
self.low, self.high = ocon.ports
self.key = hash(ocon)
def __hash__(self):
return self.key
def __lt__(self, other):
return self.origin < other.origin
def __eq__(self, other):
return self.protocol == other.protocol and \
self.low == other.low and \
self.high == other.high

View File

@ -16,6 +16,7 @@
# along with SETools. If not, see <http://www.gnu.org/licenses/>. # along with SETools. If not, see <http://www.gnu.org/licenses/>.
# #
import unittest import unittest
from socket import IPPROTO_TCP, IPPROTO_UDP
from setools import SELinuxPolicy, PolicyDifference from setools import SELinuxPolicy, PolicyDifference
@ -1236,6 +1237,52 @@ class PolicyDifferenceTest(ValidateRule, unittest.TestCase):
"""Diff: removed polcaps.""" """Diff: removed polcaps."""
self.assertSetEqual(set(["network_peer_controls"]), self.diff.removed_polcaps) self.assertSetEqual(set(["network_peer_controls"]), self.diff.removed_polcaps)
#
# portcons
#
def test_added_portcons(self):
"""Diff: added portcons."""
l = sorted(self.diff.added_portcons)
self.assertEqual(2, len(l))
portcon = l[0]
self.assertEqual(IPPROTO_TCP, portcon.protocol)
self.assertTupleEqual((2024, 2026), portcon.ports)
portcon = l[1]
self.assertEqual(IPPROTO_UDP, portcon.protocol)
self.assertTupleEqual((2024, 2024), portcon.ports)
def test_removed_portcons(self):
"""Diff: removed portcons."""
l = sorted(self.diff.removed_portcons)
self.assertEqual(2, len(l))
portcon = l[0]
self.assertEqual(IPPROTO_TCP, portcon.protocol)
self.assertTupleEqual((1024, 1026), portcon.ports)
portcon = l[1]
self.assertEqual(IPPROTO_UDP, portcon.protocol)
self.assertTupleEqual((1024, 1024), portcon.ports)
def test_modified_portcons(self):
"""Diff: modified portcons."""
l = sorted(self.diff.modified_portcons)
self.assertEqual(2, len(l))
portcon, added_context, removed_context = l[0]
self.assertEqual(IPPROTO_TCP, portcon.protocol)
self.assertTupleEqual((3024, 3026), portcon.ports)
self.assertEqual("added_user:object_r:system:s1", added_context)
self.assertEqual("removed_user:object_r:system:s0", removed_context)
portcon, added_context, removed_context = l[1]
self.assertEqual(IPPROTO_UDP, portcon.protocol)
self.assertTupleEqual((3024, 3024), portcon.ports)
self.assertEqual("added_user:object_r:system:s1", added_context)
self.assertEqual("removed_user:object_r:system:s0", removed_context)
class PolicyDifferenceTestNoDiff(unittest.TestCase): class PolicyDifferenceTestNoDiff(unittest.TestCase):
@ -1552,3 +1599,15 @@ class PolicyDifferenceTestNoDiff(unittest.TestCase):
def test_removed_polcaps(self): def test_removed_polcaps(self):
"""NoDiff: no removed polcaps.""" """NoDiff: no removed polcaps."""
self.assertFalse(self.diff.removed_polcaps) self.assertFalse(self.diff.removed_polcaps)
def test_added_portcons(self):
"""NoDiff: no added portcons."""
self.assertFalse(self.diff.added_portcons)
def test_removed_portcons(self):
"""NoDiff: no removed portcons."""
self.assertFalse(self.diff.removed_portcons)
def test_modified_portcons(self):
"""NoDiff: no modified portcons."""
self.assertFalse(self.diff.modified_portcons)

View File

@ -634,7 +634,18 @@ genfscon removed_genfs / system:object_r:system:s0
genfscon change_path /old system:object_r:system:s0 genfscon change_path /old system:object_r:system:s0
genfscon modified_genfs / -s removed_user:object_r:system:s0 genfscon modified_genfs / -s removed_user:object_r:system:s0
# matched portcons
portcon tcp 80 system:object_r:system:s0 portcon tcp 80 system:object_r:system:s0
portcon udp 80 system:object_r:system:s0
portcon udp 30-40 system:object_r:system:s0
# removed portcons
portcon udp 1024 system:object_r:system:s0
portcon tcp 1024-1026 system:object_r:system:s0
# modified portcons
portcon udp 3024 removed_user:object_r:system:s0
portcon tcp 3024-3026 removed_user:object_r:system:s0
netifcon eth0 system:object_r:system:s0 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 removed_netif system:object_r:system:s0 system:object_r:system:s0

View File

@ -634,7 +634,18 @@ genfscon added_genfs / added_user:object_r:system:s0
genfscon change_path /new system:object_r:system:s0 genfscon change_path /new system:object_r:system:s0
genfscon modified_genfs / -s added_user:object_r:system:s0 genfscon modified_genfs / -s added_user:object_r:system:s0
# matched portcons
portcon tcp 80 system:object_r:system:s0 portcon tcp 80 system:object_r:system:s0
portcon udp 80 system:object_r:system:s0
portcon udp 30-40 system:object_r:system:s0
# added portcons
portcon udp 2024 system:object_r:system:s0
portcon tcp 2024-2026 system:object_r:system:s0
# modified portcons
portcon udp 3024 added_user:object_r:system:s1
portcon tcp 3024-3026 added_user:object_r:system:s1
netifcon eth0 system:object_r:system:s0 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 added_netif system:object_r:system:s0 system:object_r:system:s0