Implement range matching in MLSRuleQuery.

Skip adding all of the range matching options in sesearch for now, as it
already has a large number of CLI options.

closes #5
This commit is contained in:
Chris PeBenito 2015-02-25 14:17:38 -05:00
parent 4d19fb964b
commit 175b7c167f
4 changed files with 383 additions and 17 deletions

View File

@ -71,7 +71,7 @@ expr.add_argument("-c", "--class", dest="tclass", default="",
expr.add_argument("-p", "--perms", metavar="PERMS", default="",
help="Comma separated list of permissions.")
expr.add_argument("-D", "--default", default="",
help="Default type of the TE/RBAC rule.")
help="Default of the rule. (type/role/range transition rules)")
expr.add_argument("-b", "--bool", dest="boolean", metavar="BOOL", default="",
help="Comma separated list of Booleans in the conditional expression.")
@ -176,7 +176,8 @@ if args.mlsrtypes:
source_regex=args.source_regex,
target=args.target,
target_regex=args.target_regex,
tclass_regex=args.tclass_regex)
tclass_regex=args.tclass_regex,
default=args.default)
# these are broken out from the above statement to prevent making a list
# with an empty string in it (split on empty string)

View File

@ -27,7 +27,9 @@ class MLSRuleQuery(rulequery.RuleQuery):
ruletype=[],
source="", source_regex=False,
target="", target_regex=False,
tclass="", tclass_regex=False):
tclass="", tclass_regex=False,
default="", default_overlap=False, default_subset=False,
default_superset=False, default_proper=False):
"""
Parameters:
policy The policy to query.
@ -49,6 +51,8 @@ class MLSRuleQuery(rulequery.RuleQuery):
self.set_source(source, regex=source_regex)
self.set_target(target, regex=target_regex)
self.set_tclass(tclass, regex=tclass_regex)
self.set_default(default, overlap=default_overlap, subset=default_subset,
superset=default_superset, proper=default_proper)
def results(self):
"""Generator which yields all matching MLS rules."""
@ -91,7 +95,55 @@ class MLSRuleQuery(rulequery.RuleQuery):
self.tclass_cmp):
continue
# TODO: something with the range
#
# Matching on range
#
if self.default and not self._match_range(
(r.default.low, r.default.high),
(self.default.low, self.default.high),
self.default_subset,
self.default_overlap,
self.default_superset,
self.default_proper):
continue
# if we get here, we have matched all available criteria
yield r
def set_default(self, default, **opts):
"""
Set the criteria for matching the rule's default range.
Parameter:
default Criteria to match the rule's default range.
Keyword Parameters:
default_subset If true, the criteria will match if it is a subset
of the rule's default range.
default_overlap If true, the criteria will match if it overlaps
any of the rule's default range.
default_superset If true, the criteria will match if it is a superset
of the rule's default range.
default_proper If true, use proper superset/subset operations.
No effect if not using set operations.
Exceptions:
NameError Invalid keyword option.
"""
if default:
self.default = self.policy.lookup_range(default)
else:
self.default = None
for k in list(opts.keys()):
if k == "subset":
self.default_subset = opts[k]
elif k == "overlap":
self.default_overlap = opts[k]
elif k == "superset":
self.default_superset = opts[k]
elif k == "proper":
self.default_proper = opts[k]
else:
raise NameError("Invalid name option: {0}".format(k))

View File

@ -57,8 +57,15 @@ sensitivity s0;
sensitivity s1;
sensitivity s2;
sensitivity s3;
sensitivity s40;
sensitivity s41;
sensitivity s42;
sensitivity s43;
sensitivity s44;
sensitivity s45;
sensitivity s46;
dominance { s0 s1 s2 s3 }
dominance { s0 s1 s2 s3 s40 s41 s42 s43 s44 s45 s46 }
category c0;
category c1;
@ -71,6 +78,13 @@ level s0:c0.c4;
level s1:c0.c4;
level s2:c0.c4;
level s3:c0.c4;
level s40:c0.c4;
level s41:c0.c4;
level s42:c0.c4;
level s43:c0.c4;
level s44:c0.c4;
level s45:c0.c4;
level s46:c0.c4;
#some constraints
mlsconstrain infoflow hi_r ((l1 dom l2) or (t1 == mls_exempt));
@ -94,7 +108,7 @@ role system types system;
# source: test1a, direct, no regex
# target: unset
# class: unset
# perms: unset
# range: unset
attribute test1a;
type test1s, test1a;
type test1t;
@ -107,7 +121,7 @@ range_transition test1FAIL test1FAIL:infoflow s1;
# source: test2s, indirect, no regex
# target: unset
# class: unset
# perms: unset
# range: unset
attribute test2a;
type test2s, test2a;
type test2t;
@ -119,7 +133,7 @@ range_transition test2a test2t:infoflow s0;
# source: test3a.*, direct, regex
# target: unset
# class: unset
# perms: unset
# range: unset
attribute test3aS;
attribute test3b;
type test3s, test3aS;
@ -134,7 +148,7 @@ range_transition test3b test3t:infoflow s3;
# source: test4(s|t), indirect, regex
# target: unset
# class: unset
# perms: unset
# range: unset
attribute test4a1;
attribute test4a2;
type test4s1, test4a1;
@ -149,7 +163,7 @@ range_transition test4FAIL test4FAIL:infoflow s3;
# source: unset
# target: test10a, direct, no regex
# class: unset
# perms: unset
# range: unset
attribute test10a;
type test10s;
type test10t, test10a;
@ -161,7 +175,7 @@ range_transition test10s test10t:infoflow2 s1;
# source: unset
# target: test11t, indirect, no regex
# class: unset
# perms: unset
# range: unset
attribute test11a;
type test11s;
type test11t, test11a;
@ -173,7 +187,7 @@ range_transition test11s test11t:infoflow2 s1;
# source: unset
# target: test12a.*, direct, regex
# class: unset
# perms: unset
# range: unset
attribute test12aPASS;
attribute test12b;
type test12s;
@ -188,7 +202,7 @@ range_transition test12s test12b:infoflow s2;
# source: unset
# target: test13(s|t), indirect, regex
# class: unset
# perms: unset
# range: unset
attribute test13a1;
attribute test13a2;
type test13s1, test13a1;
@ -203,7 +217,7 @@ range_transition test13FAIL test13FAIL:infoflow s2;
# source: unset
# target: unset
# class: infoflow2, no regex
# perms: unset
# range: unset
type test20;
range_transition test20 test20:infoflow s0;
range_transition test20 test20:infoflow7 s1;
@ -213,7 +227,7 @@ range_transition test20 test20:infoflow7 s1;
# source: unset
# target: unset
# class: infoflow3,infoflow4 , no regex
# perms: unset
# range: unset
type test21;
range_transition test21 test21:infoflow s0;
range_transition test21 test21:infoflow4 s1;
@ -224,16 +238,70 @@ range_transition test21 test21:infoflow3 s2;
# source: unset
# target: unset
# class: infoflow(5|6), regex
# perms: unset
# range: unset
type test22;
range_transition test22 test22:infoflow s0;
range_transition test22 test22:infoflow5 s1;
range_transition test22 test22:infoflow6 s2;
# test 40:
# ruletype: unset
# source: unset
# target: unset
# class: unset
# range: equal
type test40;
range_transition test40 test40:infoflow s40:c1 - s40:c0.c4;
# test 41:
# ruletype: unset
# source: unset
# target: unset
# class: unset
# range: overlap
type test41;
range_transition test41 test41:infoflow s41:c1 - s41:c1.c3;
# test 42:
# ruletype: unset
# source: unset
# target: unset
# class: unset
# range: subset
type test42;
range_transition test42 test42:infoflow s42:c1 - s42:c1.c3;
# test 43:
# ruletype: unset
# source: unset
# target: unset
# class: unset
# range: superset
type test43;
range_transition test43 test43:infoflow s43:c1 - s43:c1.c3;
# test 44:
# ruletype: unset
# source: unset
# target: unset
# class: unset
# range: proper subset
type test44;
range_transition test44 test44:infoflow s44:c1 - s44:c1.c3;
# test 45:
# ruletype: unset
# source: unset
# target: unset
# class: unset
# range: proper superset
type test45;
range_transition test45 test45:infoflow s45:c1 - s45:c1.c3;
################################################################################
#users
user system roles system level s0 range s0 - s2:c0.c4;
user system roles system level s0 range s0 - s46:c0.c4;
#normal constraints
constrain infoflow hi_w (u1 == u2);

View File

@ -177,3 +177,248 @@ class MLSRuleQueryTest(unittest.TestCase):
self.assertEqual(r[1].tclass, "infoflow6")
self.assertEqual(r[1].default, "s2")
self.assertRaises(RuleNotConditional, getattr, r[1], "conditional")
def test_040_range_exact(self):
"""MLS rule query query with context range exact match"""
q = MLSRuleQuery(self.p, default="s40:c1 - s40:c0.c4")
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test40")
self.assertEqual(r[0].target, "test40")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s40:c1 - s40:c0.c4")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_041_range_overlap1(self):
"""MLS rule query query with context range overlap match (equal)"""
q = MLSRuleQuery(self.p, default="s41:c1 - s41:c0.c4", default_overlap=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test41")
self.assertEqual(r[0].target, "test41")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s41:c1 - s41:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_041_range_overlap2(self):
"""MLS rule query query with context range overlap match (subset)"""
q = MLSRuleQuery(self.p, default="s41:c1,c2 - s41:c0.c3", default_overlap=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test41")
self.assertEqual(r[0].target, "test41")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s41:c1 - s41:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_041_range_overlap3(self):
"""MLS rule query query with context range overlap match (superset)"""
q = MLSRuleQuery(self.p, default="s41 - s41:c0.c4", default_overlap=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test41")
self.assertEqual(r[0].target, "test41")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s41:c1 - s41:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_041_range_overlap4(self):
"""MLS rule query query with context range overlap match (overlap low level)"""
q = MLSRuleQuery(self.p, default="s41 - s41:c1,c2", default_overlap=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test41")
self.assertEqual(r[0].target, "test41")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s41:c1 - s41:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_041_range_overlap5(self):
"""MLS rule query query with context range overlap match (overlap high level)"""
q = MLSRuleQuery(self.p, default="s41:c1,c2 - s41:c0.c4", default_overlap=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test41")
self.assertEqual(r[0].target, "test41")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s41:c1 - s41:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_042_range_subset1(self):
"""MLS rule query query with context range subset match"""
q = MLSRuleQuery(self.p, default="s42:c1,c2 - s42:c0.c3", default_overlap=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test42")
self.assertEqual(r[0].target, "test42")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s42:c1 - s42:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_042_range_subset2(self):
"""MLS rule query query with context range subset match (equal)"""
q = MLSRuleQuery(self.p, default="s42:c1 - s42:c1.c3", default_overlap=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test42")
self.assertEqual(r[0].target, "test42")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s42:c1 - s42:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_043_range_superset1(self):
"""MLS rule query query with context range superset match"""
q = MLSRuleQuery(self.p, default="s43 - s43:c0.c4", default_superset=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test43")
self.assertEqual(r[0].target, "test43")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s43:c1 - s43:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_043_range_superset2(self):
"""MLS rule query query with context range superset match (equal)"""
q = MLSRuleQuery(self.p, default="s43:c1 - s43:c1.c3", default_superset=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test43")
self.assertEqual(r[0].target, "test43")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s43:c1 - s43:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_044_range_proper_subset1(self):
"""MLS rule query query with context range proper subset match"""
q = MLSRuleQuery(self.p, default="s44:c1,c2", default_subset=True, default_proper=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test44")
self.assertEqual(r[0].target, "test44")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s44:c1 - s44:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_044_range_proper_subset2(self):
"""MLS rule query query with context range proper subset match (equal)"""
q = MLSRuleQuery(self.p,
default="s44:c1 - s44:c1.c3", default_subset=True, default_proper=True)
r = sorted(q.results())
self.assertEqual(len(r), 0)
def test_044_range_proper_subset3(self):
"""MLS rule query query with context range proper subset match (equal low only)"""
q = MLSRuleQuery(self.p,
default="s44:c1 - s44:c1.c2", default_subset=True, default_proper=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test44")
self.assertEqual(r[0].target, "test44")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s44:c1 - s44:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_044_range_proper_subset4(self):
"""MLS rule query query with context range proper subset match (equal high only)"""
q = MLSRuleQuery(self.p,
default="s44:c1,c2 - s44:c1.c3", default_subset=True, default_proper=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test44")
self.assertEqual(r[0].target, "test44")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s44:c1 - s44:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_045_range_proper_superset1(self):
"""MLS rule query query with context range proper superset match"""
q = MLSRuleQuery(self.p,
default="s45 - s45:c0.c4", default_superset=True, default_proper=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test45")
self.assertEqual(r[0].target, "test45")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s45:c1 - s45:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_045_range_proper_superset2(self):
"""MLS rule query query with context range proper superset match (equal)"""
q = MLSRuleQuery(self.p,
default="s45:c1 - s45:c1.c3", default_superset=True, default_proper=True)
r = sorted(q.results())
self.assertEqual(len(r), 0)
def test_045_range_proper_superset3(self):
"""MLS rule query query with context range proper superset match (equal low)"""
q = MLSRuleQuery(self.p,
default="s45:c1 - s45:c1.c4", default_superset=True, default_proper=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test45")
self.assertEqual(r[0].target, "test45")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s45:c1 - s45:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_045_range_proper_superset4(self):
"""MLS rule query query with context range proper superset match (equal high)"""
q = MLSRuleQuery(self.p,
default="s45 - s45:c1.c3", default_superset=True, default_proper=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test45")
self.assertEqual(r[0].target, "test45")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s45:c1 - s45:c1.c3")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")