Add MLSRuleQuery unit tests.

Turns out the rules are always expanded, so indirect options had
no effect.
This commit is contained in:
Chris PeBenito 2014-11-06 19:59:02 -05:00
parent 0fb0940fe3
commit 248df414ab
4 changed files with 448 additions and 14 deletions

View File

@ -25,25 +25,19 @@ class MLSRuleQuery(rulequery.RuleQuery):
def __init__(self, policy,
ruletype=[],
source="", source_indirect=True, source_regex=False,
target="", target_indirect=True, target_regex=False,
source="", source_regex=False,
target="", target_regex=False,
tclass="", tclass_regex=False):
"""
Parameters:
policy The policy to query.
ruletype The rule type(s) to match.
source The name of the source type/attribute to match.
source_indirect If true, members of an attribute will be
matched rather than the attribute itself.
source_regex If true, regular expression matching will
be used on the source type/attribute.
Obeys the source_indirect option.
target The name of the target type/attribute to match.
target_indirect If true, members of an attribute will be
matched rather than the attribute itself.
target_regex If true, regular expression matching will
be used on the target type/attribute.
Obeys target_indirect option.
tclass The object class(es) to match.
tclass_regex If true, use a regular expression for
matching the rule's object class.
@ -52,8 +46,8 @@ class MLSRuleQuery(rulequery.RuleQuery):
self.policy = policy
self.set_ruletype(ruletype)
self.set_source(source, indirect=source_indirect, regex=source_regex)
self.set_target(target, indirect=target_indirect, regex=target_regex)
self.set_source(source, regex=source_regex)
self.set_target(target, regex=target_regex)
self.set_tclass(tclass, regex=tclass_regex)
def results(self):
@ -70,10 +64,9 @@ class MLSRuleQuery(rulequery.RuleQuery):
#
# Matching on source type
#
if self.source and not self._match_indirect_regex(
if self.source and not self._match_regex(
r.source,
self.source,
self.source_indirect,
self.source_regex,
self.source_cmp):
continue
@ -81,10 +74,9 @@ class MLSRuleQuery(rulequery.RuleQuery):
#
# Matching on target type
#
if self.target and not self._match_indirect_regex(
if self.target and not self._match_regex(
r.target,
self.target,
self.target_indirect,
self.target_regex,
self.target_cmp):
continue

View File

@ -21,6 +21,7 @@ from . import dta
from . import fsusequery
from . import genfsconquery
from . import initsidquery
from . import mlsrulequery
from . import nodeconquery
from . import objclassquery
from . import polcapquery

260
tests/mlsrulequery.conf Normal file
View File

@ -0,0 +1,260 @@
class infoflow
class infoflow2
class infoflow3
class infoflow4
class infoflow5
class infoflow6
class infoflow7
sid kernel
sid security
common infoflow
{
low_w
med_w
hi_w
low_r
med_r
hi_r
}
class infoflow
inherits infoflow
class infoflow2
inherits infoflow
{
super_w
super_r
}
class infoflow3
{
null
}
class infoflow4
inherits infoflow
class infoflow5
inherits infoflow
class infoflow6
inherits infoflow
class infoflow7
inherits infoflow
{
super_w
super_r
super_none
super_both
super_unmapped
}
sensitivity s0;
sensitivity s1;
sensitivity s2;
sensitivity s3;
dominance { s0 s1 s2 s3 }
category c0;
category c1;
category c2;
category c3;
category c4;
#level decl
level s0:c0.c4;
level s1:c0.c4;
level s2:c0.c4;
level s3:c0.c4;
#some constraints
mlsconstrain infoflow hi_r ((l1 dom l2) or (t1 == mls_exempt));
attribute mls_exempt;
type system;
role system;
role system types system;
################################################################################
# Type enforcement declarations and rules
########################################
#
# TE Rule Query
#
# test 1
# ruletype: unset
# source: test1a, direct, no regex
# target: unset
# class: unset
# perms: unset
attribute test1a;
type test1s, test1a;
type test1t;
type test1FAIL, test1a;
range_transition test1a test1t:infoflow s0;
range_transition test1FAIL test1FAIL:infoflow s1;
# test 2
# ruletype: unset
# source: test2s, indirect, no regex
# target: unset
# class: unset
# perms: unset
attribute test2a;
type test2s, test2a;
type test2t;
range_transition test2a test2t:infoflow s0;
#range_transition test2s test2t:infoflow s1;
# test 3
# ruletype: unset
# source: test3a.*, direct, regex
# target: unset
# class: unset
# perms: unset
attribute test3aS;
attribute test3b;
type test3s, test3aS;
type test3t;
type test3aFAIL, test3b;
range_transition test3s test3t:infoflow s1;
range_transition test3aS test3t:infoflow2 s2;
range_transition test3b test3t:infoflow s3;
# test 4
# ruletype: unset
# source: test4(s|t), indirect, regex
# target: unset
# class: unset
# perms: unset
attribute test4a1;
attribute test4a2;
type test4s1, test4a1;
type test4t1, test4a2;
type test4FAIL;
range_transition test4a1 test4a1:infoflow s1;
range_transition test4a2 test4a2:infoflow2 s2;
range_transition test4FAIL test4FAIL:infoflow s3;
# test 10
# ruletype: unset
# source: unset
# target: test10a, direct, no regex
# class: unset
# perms: unset
attribute test10a;
type test10s;
type test10t, test10a;
range_transition test10s test10a:infoflow s0;
range_transition test10s test10t:infoflow2 s1;
# test 11
# ruletype: unset
# source: unset
# target: test11t, indirect, no regex
# class: unset
# perms: unset
attribute test11a;
type test11s;
type test11t, test11a;
range_transition test11s test11a:infoflow s0;
range_transition test11s test11t:infoflow2 s1;
# test 12
# ruletype: unset
# source: unset
# target: test12a.*, direct, regex
# class: unset
# perms: unset
attribute test12aPASS;
attribute test12b;
type test12s;
type test12t, test12aPASS;
type test12aFAIL, test12b;
range_transition test12s test12t:infoflow s0;
range_transition test12s test12aPASS:infoflow2 s1;
range_transition test12s test12b:infoflow s2;
# test 13
# ruletype: unset
# source: unset
# target: test13(s|t), indirect, regex
# class: unset
# perms: unset
attribute test13a1;
attribute test13a2;
type test13s1, test13a1;
type test13t1, test13a2;
type test13FAIL;
range_transition test13a1 test13a1:infoflow s0;
range_transition test13a2 test13a2:infoflow s1;
range_transition test13FAIL test13FAIL:infoflow s2;
# test 20
# ruletype: unset
# source: unset
# target: unset
# class: infoflow2, no regex
# perms: unset
type test20;
range_transition test20 test20:infoflow s0;
range_transition test20 test20:infoflow7 s1;
# test 21
# ruletype: unset
# source: unset
# target: unset
# class: infoflow3,infoflow4 , no regex
# perms: unset
type test21;
range_transition test21 test21:infoflow s0;
range_transition test21 test21:infoflow4 s1;
range_transition test21 test21:infoflow3 s2;
# test 22
# ruletype: unset
# source: unset
# target: unset
# class: infoflow(5|6), regex
# perms: unset
type test22;
range_transition test22 test22:infoflow s0;
range_transition test22 test22:infoflow5 s1;
range_transition test22 test22:infoflow6 s2;
################################################################################
#users
user system roles system level s0 range s0 - s2:c0.c4;
#normal constraints
constrain infoflow hi_w (u1 == u2);
#isids
sid kernel system:system:system:s0
sid security system:system:system:s0
#fs_use
fs_use_trans devpts system:object_r:system:s0;
fs_use_xattr ext3 system:object_r:system:s0;
fs_use_task pipefs system:object_r:system:s0;
#genfscon
genfscon proc / system:object_r:system:s0
genfscon proc /sys system:object_r:system:s0
genfscon selinuxfs / system:object_r:system:s0
portcon tcp 80 system:object_r:system:s0
netifcon eth0 system:object_r:system:s0 system: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

181
tests/mlsrulequery.py Normal file
View File

@ -0,0 +1,181 @@
# Copyright 2014, 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 General Public License as published by
# the Free Software Foundation, either version 2 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with SETools. If not, see <http://www.gnu.org/licenses/>.
#
import unittest
from setools import SELinuxPolicy
from setools.mlsrulequery import MLSRuleQuery
from setools.policyrep.rule import RuleNotConditional
# Note: the test policy has been written assuming range_transition
# statements could have attributes. However, range_transition
# statements are always expanded, so the below unit tests
# have been adjusted to this fact (hence a "FAIL" in one of the
# expected type names)
class MLSRuleQueryTest(unittest.TestCase):
def setUp(self):
self.p = SELinuxPolicy("tests/mlsrulequery.conf")
def test_000_unset(self):
"""MLS rule query with no criteria."""
# query with no parameters gets all MLS rules.
for numrules, r in enumerate(self.p.mlsrules(), start=1):
pass
q = MLSRuleQuery(self.p)
for q_numrules, r in enumerate(q.results(), start=1):
pass
self.assertEqual(numrules, q_numrules)
def test_001_source_direct(self):
"""MLS rule query with exact, direct, source match."""
q = MLSRuleQuery(
self.p, source="test1s", source_regex=False)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test1s")
self.assertEqual(r[0].target, "test1t")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s0")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_003_source_direct_regex(self):
"""MLS rule query with regex, direct, source match."""
q = MLSRuleQuery(
self.p, source="test3(s|aS)", source_regex=True)
r = sorted(q.results())
self.assertEqual(len(r), 2)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test3s")
self.assertEqual(r[0].target, "test3t")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s1")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
self.assertEqual(r[1].ruletype, "range_transition")
self.assertEqual(r[1].source, "test3s")
self.assertEqual(r[1].target, "test3t")
self.assertEqual(r[1].tclass, "infoflow2")
self.assertEqual(r[1].default, "s2")
self.assertRaises(RuleNotConditional, getattr, r[1], "conditional")
def test_010_target_direct(self):
"""MLS rule query with exact, direct, target match."""
q = MLSRuleQuery(
self.p, target="test10t", target_regex=False)
r = sorted(q.results())
self.assertEqual(len(r), 2)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test10s")
self.assertEqual(r[0].target, "test10t")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s0")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
self.assertEqual(r[1].ruletype, "range_transition")
self.assertEqual(r[1].source, "test10s")
self.assertEqual(r[1].target, "test10t")
self.assertEqual(r[1].tclass, "infoflow2")
self.assertEqual(r[1].default, "s1")
self.assertRaises(RuleNotConditional, getattr, r[1], "conditional")
def test_012_target_direct_regex(self):
"""MLS rule query with regex, direct, target match."""
q = MLSRuleQuery(
self.p, target="test12a.*", target_regex=True)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test12s")
self.assertEqual(r[0].target, "test12aFAIL")
self.assertEqual(r[0].tclass, "infoflow")
self.assertEqual(r[0].default, "s2")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_020_class(self):
"""MLS rule query with exact object class match."""
q = MLSRuleQuery(self.p, tclass="infoflow7", tclass_regex=False)
r = sorted(q.results())
self.assertEqual(len(r), 1)
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test20")
self.assertEqual(r[0].target, "test20")
self.assertEqual(r[0].tclass, "infoflow7")
self.assertEqual(r[0].default, "s1")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
def test_021_class_list(self):
"""MLS rule query with object class list match."""
q = MLSRuleQuery(
self.p, tclass=["infoflow3", "infoflow4"], tclass_regex=False)
r = sorted(q.results())
self.assertEqual(len(r), 2)
# verify first rule
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test21")
self.assertEqual(r[0].target, "test21")
self.assertEqual(r[0].tclass, "infoflow3")
self.assertEqual(r[0].default, "s2")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
# verify second rule
self.assertEqual(r[1].ruletype, "range_transition")
self.assertEqual(r[1].source, "test21")
self.assertEqual(r[1].target, "test21")
self.assertEqual(r[1].tclass, "infoflow4")
self.assertEqual(r[1].default, "s1")
self.assertRaises(RuleNotConditional, getattr, r[1], "conditional")
def test_022_class_regex(self):
"""MLS rule query with object class regex match."""
q = MLSRuleQuery(self.p, tclass="infoflow(5|6)", tclass_regex=True)
r = sorted(q.results())
self.assertEqual(len(r), 2)
# verify first rule
self.assertEqual(r[0].ruletype, "range_transition")
self.assertEqual(r[0].source, "test22")
self.assertEqual(r[0].target, "test22")
self.assertEqual(r[0].tclass, "infoflow5")
self.assertEqual(r[0].default, "s1")
self.assertRaises(RuleNotConditional, getattr, r[0], "conditional")
# verify second rule
self.assertEqual(r[1].ruletype, "range_transition")
self.assertEqual(r[1].source, "test22")
self.assertEqual(r[1].target, "test22")
self.assertEqual(r[1].tclass, "infoflow6")
self.assertEqual(r[1].default, "s2")
self.assertRaises(RuleNotConditional, getattr, r[1], "conditional")