mirror of
https://github.com/SELinuxProject/setools
synced 2025-03-02 19:08:36 +00:00
Add MLSRuleQuery unit tests.
Turns out the rules are always expanded, so indirect options had no effect.
This commit is contained in:
parent
0fb0940fe3
commit
248df414ab
@ -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
|
||||
|
@ -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
260
tests/mlsrulequery.conf
Normal 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
181
tests/mlsrulequery.py
Normal 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")
|
Loading…
Reference in New Issue
Block a user