Implement level and range criteria for UserQuery.

This commit is contained in:
Chris PeBenito 2015-03-02 09:15:22 -05:00
parent 43c438f14e
commit 7e8ea8438c
4 changed files with 431 additions and 62 deletions

View File

@ -133,6 +133,27 @@ class PolicyQuery(object):
else:
return (crit_low == obj_low and obj_high == crit_high)
@staticmethod
def _match_level(obj, criteria, dom, domby, incomp):
"""
Match the an MLS level.
obj The level to match.
criteria The criteria to match. (a level)
dom If true, the criteria will match if it dominates obj.
domby If true, the criteria will match if it is dominated by obj.
incomp If true, the criteria will match if it is incomparable to obj.
"""
if dom:
return (criteria >= obj)
elif domby:
return (criteria <= obj)
elif incomp:
return (criteria ^ obj)
else:
return (criteria == obj)
def results(self):
"""
Generator which returns the matches for the query. This method

View File

@ -27,26 +27,41 @@ class UserQuery(compquery.ComponentQuery):
def __init__(self, policy,
name="", name_regex=False,
roles=set(), roles_equal=False, roles_regex=False):
roles=set(), roles_equal=False, roles_regex=False,
level="", level_dom=False, level_domby=False, level_incomp=False,
range_="", range_overlap=False, range_subset=False,
range_superset=False, range_proper=False):
"""
Parameter:
policy The policy to query.
name The user name to match.
name_regex If true, regular expression matching
will be used on the user names.
roles The attribute to match.
roles_equal If true, only types with role sets
that are equal to the criteria will
match. Otherwise, any intersection
will match.
roles_regex If true, regular expression matching
will be used on the role names instead
of set logic.
policy The policy to query.
name The user name to match.
name_regex If true, regular expression matching
will be used on the user names.
roles The attribute to match.
roles_equal If true, only types with role sets
that are equal to the criteria will
match. Otherwise, any intersection
will match.
roles_regex If true, regular expression matching
will be used on the role names instead
of set logic.
range_ The criteria to match the user's range.
range_subset If true, the criteria will match if it is a subset
of the user's range.
range_overlap If true, the criteria will match if it overlaps
any of the user's range.
range_superset If true, the criteria will match if it is a superset
of the user's range.
range_proper If true, use proper superset/subset operations.
No effect if not using set operations.
"""
self.policy = policy
self.set_name(name, regex=name_regex)
self.set_roles(roles, regex=roles_regex, equal=roles_equal)
self.set_level(level, dom=level_dom, domby=level_domby, incomp=level_incomp)
self.set_range(range_, overlap=range_overlap, subset=range_subset,
superset=range_superset, proper=range_proper)
def results(self):
"""Generator which yields all matching users."""
@ -65,10 +80,94 @@ class UserQuery(compquery.ComponentQuery):
self.roles_regex):
continue
# TODO: default level and range
if self.level and not self._match_level(
u.mls_level,
self.level,
self.level_dom,
self.level_domby,
self.level_incomp):
continue
if self.range_ and not self._match_range(
(u.mls_range.low, u.mls_range.high),
(self.range_.low, self.range_.high),
self.range_subset,
self.range_overlap,
self.range_superset,
self.range_proper):
continue
yield u
def set_level(self, level, **opts):
"""
Set the criteria for matching the user's default level.
Parameter:
level Criteria to match the user's default level.
Keyword Parameters:
dom If true, the criteria will match if it dominates the user's default level.
domby If true, the criteria will match if it is dominated by the user's default level.
incomp If true, the criteria will match if it incomparable to the user's default level.
Exceptions:
NameError Invalid keyword option.
"""
if level:
self.level = self.policy.lookup_level(level)
else:
self.level = None
for k in list(opts.keys()):
if k == "dom":
self.level_dom = opts[k]
elif k == "domby":
self.level_domby = opts[k]
elif k == "incomp":
self.level_incomp = opts[k]
else:
raise NameError("Invalid name option: {0}".format(k))
def set_range(self, range_, **opts):
"""
Set the criteria for matching the user's range.
Parameter:
range_ Criteria to match the user's range.
Keyword Parameters:
subset If true, the criteria will match if it is a subset
of the user's range.
overlap If true, the criteria will match if it overlaps
any of the user's range.
superset If true, the criteria will match if it is a superset
of the user's range.
proper If true, use proper superset/subset operations.
No effect if not using set operations.
Exceptions:
NameError Invalid keyword option.
"""
if range_:
self.range_ = self.policy.lookup_range(range_)
else:
self.range_ = None
for k in list(opts.keys()):
if k == "subset":
self.range_subset = opts[k]
elif k == "overlap":
self.range_overlap = opts[k]
elif k == "superset":
self.range_superset = opts[k]
elif k == "proper":
self.range_proper = opts[k]
else:
raise NameError("Invalid name option: {0}".format(k))
def set_roles(self, roles, **opts):
"""
Set the criteria for the users's roles.

View File

@ -53,20 +53,33 @@ inherits infoflow
super_unmapped
}
sensitivity low_s;
sensitivity medium_s alias med;
sensitivity high_s;
sensitivity s0;
sensitivity s1;
sensitivity s2;
sensitivity s3;
sensitivity s4;
sensitivity s5;
sensitivity s6;
dominance { low_s med high_s }
dominance { s0 s1 s2 s3 s4 s5 s6 }
category here;
category there;
category elsewhere alias lost;
category c0;
category c1;
category c2;
category c3;
category c4;
category c5;
category c6;
category c7;
#level decl
level low_s:here.there;
level med:here, elsewhere;
level high_s:here.lost;
level s0:c0.c7;
level s1:c0.c7;
level s2:c0.c7;
level s3:c0.c7;
level s4:c0.c7;
level s5:c0.c7;
level s6:c0.c7;
#some constraints
mlsconstrain infoflow hi_r ((l1 dom l2) or (t1 == mls_exempt));
@ -105,75 +118,143 @@ role test12c_r;
# test 1
# name: test1_u
# roles: unset
user test1_u roles test1_r level med range med;
user test1_u roles test1_r level s3:c5,c7 range s3:c5,c7;
# test 2
# name: test2_u(1|2) regex
# roles: unset
user test2_u1 roles test2a_r level med range med;
user test2_u2 roles test2b_r level med range med;
user test2_u1 roles test2a_r level s3:c5,c7 range s3:c5,c7;
user test2_u2 roles test2b_r level s3:c5,c7 range s3:c5,c7;
# test 10
# name: unset
# roles: test10a_r,test10b_r
user test10_u1 roles test10a_r level med range med;
user test10_u2 roles { test10a_r test10b_r } level med range med;
user test10_u3 roles { test10a_r test10b_r test10c_r } level med range med;
user test10_u4 roles { test10b_r test10c_r } level med range med;
user test10_u5 roles { test10a_r test10c_r } level med range med;
user test10_u6 roles test10b_r level med range med;
user test10_u7 roles test10c_r level med range med;
user test10_u1 roles test10a_r level s3:c5,c7 range s3:c5,c7;
user test10_u2 roles { test10a_r test10b_r } level s3:c5,c7 range s3:c5,c7;
user test10_u3 roles { test10a_r test10b_r test10c_r } level s3:c5,c7 range s3:c5,c7;
user test10_u4 roles { test10b_r test10c_r } level s3:c5,c7 range s3:c5,c7;
user test10_u5 roles { test10a_r test10c_r } level s3:c5,c7 range s3:c5,c7;
user test10_u6 roles test10b_r level s3:c5,c7 range s3:c5,c7;
user test10_u7 roles test10c_r level s3:c5,c7 range s3:c5,c7;
# test 11
# name: unset
# roles: test11a_r,test11b_r equal
user test11_u1 roles test11a_r level med range med;
user test11_u2 roles { test11a_r test11b_r } level med range med;
user test11_u3 roles { test11a_r test11b_r test11c_r } level med range med;
user test11_u4 roles { test11b_r test11c_r } level med range med;
user test11_u5 roles { test11a_r test11c_r } level med range med;
user test11_u6 roles test11b_r level med range med;
user test11_u7 roles test11c_r level med range med;
user test11_u1 roles test11a_r level s3:c5,c7 range s3:c5,c7;
user test11_u2 roles { test11a_r test11b_r } level s3:c5,c7 range s3:c5,c7;
user test11_u3 roles { test11a_r test11b_r test11c_r } level s3:c5,c7 range s3:c5,c7;
user test11_u4 roles { test11b_r test11c_r } level s3:c5,c7 range s3:c5,c7;
user test11_u5 roles { test11a_r test11c_r } level s3:c5,c7 range s3:c5,c7;
user test11_u6 roles test11b_r level s3:c5,c7 range s3:c5,c7;
user test11_u7 roles test11c_r level s3:c5,c7 range s3:c5,c7;
# test 12
# name: unset
# roles: test12(a|b)_r regex
user test12_u1 roles test12a_r level med range med;
user test12_u2 roles { test12a_r test12b_r } level med range med;
user test12_u3 roles { test12a_r test12b_r test12c_r } level med range med;
user test12_u4 roles { test12b_r test12c_r } level med range med;
user test12_u5 roles { test12a_r test12c_r } level med range med;
user test12_u6 roles test12b_r level med range med;
user test12_u7 roles test12c_r level med range med;
user test12_u1 roles test12a_r level s3:c5,c7 range s3:c5,c7;
user test12_u2 roles { test12a_r test12b_r } level s3:c5,c7 range s3:c5,c7;
user test12_u3 roles { test12a_r test12b_r test12c_r } level s3:c5,c7 range s3:c5,c7;
user test12_u4 roles { test12b_r test12c_r } level s3:c5,c7 range s3:c5,c7;
user test12_u5 roles { test12a_r test12c_r } level s3:c5,c7 range s3:c5,c7;
user test12_u6 roles test12b_r level s3:c5,c7 range s3:c5,c7;
user test12_u7 roles test12c_r level s3:c5,c7 range s3:c5,c7;
# test 20
# name: unset
# roles: unset
# level: equal
# range: unset
user test20 roles system level s3:c0,c4 range s3 - s3:c0.c4,c7;
# test 21
# name: unset
# roles: unset
# level: high, dom
# range: unset
user test21 roles system level s2:c1,c4 range s2 - s2:c0.c4,c7;
# test 22
# name: unset
# roles: unset
# level: high, domby
# range: unset
user test22 roles system level s4:c2,c4 range s4 - s4:c0.c4,c7;
# test 23
# name: unset
# roles: unset
# level: high, incomp
# range: unset
user test23 roles system level s3:c6 range s3 - s3:c0.c7;
# test 40:
# name: unset
# roles: unset
# level: unset
# range: equal
user test40 roles system level s0:c5 range s0:c5 - s0:c0.c5;
# test 41:
# name: unset
# roles: unset
# level: unset
# range: overlap
user test41 roles system level s1:c5 range s1:c5 - s1:c1.c3,c5;
# test 42:
# name: unset
# roles: unset
# level: unset
# range: subset
user test42 roles system level s2:c5 range s2:c5 - s2:c1.c3,c5;
# test 43:
# name: unset
# roles: unset
# level: unset
# range: superset
user test43 roles system level s3:c5 range s3:c5 - s3:c1.c3,c5,c6;
# test 44:
# name: unset
# roles: unset
# level: unset
# range: proper subset
user test44 roles system level s4:c5 range s4:c5 - s4:c1.c3,c5;
# test 45:
# name: unset
# roles: unset
# level: unset
# range: proper superset
user test45 roles system level s5:c5 range s5:c5 - s5:c1.c3,c5;
################################################################################
#users
user system roles system level med range low_s - high_s:here.lost;
user system roles system level s0:c5 range s0:c5;
#normal constraints
constrain infoflow hi_w (u1 == u2);
#isids
sid kernel system:system:system:medium_s:here
sid security system:system:system:high_s:lost
sid kernel system:system:system:s0:c5
sid security system:system:system:s0:c5
#fs_use
fs_use_trans devpts system:object_r:system:low_s;
fs_use_xattr ext3 system:object_r:system:low_s;
fs_use_task pipefs system:object_r:system:low_s;
fs_use_trans devpts system:object_r:system:s0:c5;
fs_use_xattr ext3 system:object_r:system:s0:c5;
fs_use_task pipefs system:object_r:system:s0:c5;
#genfscon
genfscon proc / system:object_r:system:med
genfscon proc /sys system:object_r:system:low_s
genfscon selinuxfs / system:object_r:system:high_s:here.there
genfscon proc / system:object_r:system:s3
genfscon proc /sys system:object_r:system:s0:c5
genfscon selinuxfs / system:object_r:system:s3:c0.c4
portcon tcp 80 system:object_r:system:low_s
portcon tcp 80 system:object_r:system:s0:c5
netifcon eth0 system:object_r:system:low_s system:object_r:system:low_s
netifcon eth0 system:object_r:system:s0:c5 system:object_r:system:s0:c5
nodecon 127.0.0.1 255.255.255.255 system:object_r:system:low_s:here
nodecon ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system:object_r:system:low_s:here
nodecon 127.0.0.1 255.255.255.255 system:object_r:system:s0:c5
nodecon ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system:object_r:system:s0:c5

View File

@ -1,4 +1,4 @@
# Copyright 2014, Tresys Technology, LLC
# Copyright 2014-2015, Tresys Technology, LLC
#
# This file is part of SETools.
#
@ -73,3 +73,171 @@ class UserQueryTest(unittest.TestCase):
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test12_u1", "test12_u2", "test12_u3",
"test12_u4", "test12_u5", "test12_u6"], users)
def test_020_level_equal(self):
"""User query with default level equality."""
q = UserQuery(self.p, level="s3:c0,c4")
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test20"], users)
def test_021_level_dom1(self):
"""User query with default level dominance."""
q = UserQuery(self.p, level="s2:c1,c2,c4", level_dom=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test21"], users)
def test_021_level_dom2(self):
"""User query with default level dominance (equal)."""
q = UserQuery(self.p, level="s2:c1,c4", level_dom=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test21"], users)
def test_022_level_domby1(self):
"""User query with default level dominated-by."""
q = UserQuery(self.p, level="s3:c2", level_domby=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test22"], users)
def test_022_level_domby2(self):
"""User query with default level dominated-by (equal)."""
q = UserQuery(self.p, level="s3:c2,c4", level_domby=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test22"], users)
def test_023_level_incomp(self):
"""User query with default level icomparable."""
q = UserQuery(self.p, level="s5:c0.c5,c7", level_incomp=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test23"], users)
def test_040_range_exact(self):
"""User query with range exact match"""
q = UserQuery(self.p, range_="s0:c5 - s0:c0.c5")
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test40"], users)
def test_041_range_overlap1(self):
"""User query with range overlap match (equal)"""
q = UserQuery(self.p, range_="s1:c5 - s1:c1.c3,c5", range_overlap=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test41"], users)
def test_041_range_overlap2(self):
"""User query with range overlap match (subset)"""
q = UserQuery(self.p, range_="s1:c2,c5 - s1:c2.c3,c5", range_overlap=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test41"], users)
def test_041_range_overlap3(self):
"""User query with range overlap match (superset)"""
q = UserQuery(self.p, range_="s1 - s1:c0.c5", range_overlap=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test41"], users)
def test_041_range_overlap4(self):
"""User query with range overlap match (overlap low level)"""
q = UserQuery(self.p, range_="s1:c5 - s1:c2,c5", range_overlap=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test41"], users)
def test_041_range_overlap5(self):
"""User query with range overlap match (overlap high level)"""
q = UserQuery(self.p, range_="s1:c5,c2 - s1:c1.c3,c5", range_overlap=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test41"], users)
def test_042_range_subset1(self):
"""User query with range subset match"""
q = UserQuery(self.p, range_="s2:c2,c5 - s2:c2.c3,c5", range_overlap=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test42"], users)
def test_042_range_subset2(self):
"""User query with range subset match (equal)"""
q = UserQuery(self.p, range_="s2:c5 - s2:c1.c3,c5", range_overlap=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test42"], users)
def test_043_range_superset1(self):
"""User query with range superset match"""
q = UserQuery(self.p, range_="s3 - s3:c0.c6", range_superset=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test43"], users)
def test_043_range_superset2(self):
"""User query with range superset match (equal)"""
q = UserQuery(self.p, range_="s3:c5 - s3:c1.c3,c5.c6", range_superset=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test43"], users)
def test_044_range_proper_subset1(self):
"""User query with range proper subset match"""
q = UserQuery(self.p, range_="s4:c2,c5", range_subset=True, range_proper=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test44"], users)
def test_044_range_proper_subset2(self):
"""User query with range proper subset match (equal)"""
q = UserQuery(self.p, range_="s4:c5 - s4:c1.c3,c5", range_subset=True, range_proper=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual([], users)
def test_044_range_proper_subset3(self):
"""User query with range proper subset match (equal low)"""
q = UserQuery(self.p, range_="s4:c5 - s4:c1.c2,c5", range_subset=True, range_proper=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test44"], users)
def test_044_range_proper_subset4(self):
"""User query with range proper subset match (equal high)"""
q = UserQuery(self.p, range_="s4:c1,c5 - s4:c1.c3,c5", range_subset=True, range_proper=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test44"], users)
def test_045_range_proper_superset1(self):
"""User query with range proper superset match"""
q = UserQuery(self.p, range_="s5 - s5:c0.c5", range_superset=True, range_proper=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test45"], users)
def test_045_range_proper_superset2(self):
"""User query with range proper superset match (equal)"""
q = UserQuery(self.p, range_="s5:c5 - s5:c1.c3,c5", range_superset=True, range_proper=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual([], users)
def test_045_range_proper_superset3(self):
"""User query with range proper superset match (equal low)"""
q = UserQuery(self.p, range_="s5:c5 - s5:c1.c5", range_superset=True, range_proper=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test45"], users)
def test_045_range_proper_superset4(self):
"""User query with range proper superset match (equal high)"""
q = UserQuery(self.p, range_="s5 - s5:c1.c3,c5", range_superset=True, range_proper=True)
users = sorted(str(u) for u in q.results())
self.assertListEqual(["test45"], users)