mirror of
https://github.com/SELinuxProject/setools
synced 2025-04-27 13:49:38 +00:00
Implement part of ConstraintQuery.
Still requires criteria on the constraint expression. closes #6 closes #12
This commit is contained in:
parent
a696a5a43c
commit
8812f02411
7
seinfo
7
seinfo
@ -97,6 +97,13 @@ try:
|
|||||||
q = setools.objclassquery.ObjClassQuery(p)
|
q = setools.objclassquery.ObjClassQuery(p)
|
||||||
components.append(("Classes", q))
|
components.append(("Classes", q))
|
||||||
|
|
||||||
|
if args.constraintquery or args.all:
|
||||||
|
if isinstance(args.constraintquery, str):
|
||||||
|
q = setools.constraintquery.ConstraintQuery(p, tclass=args.constraintquery)
|
||||||
|
else:
|
||||||
|
q = setools.constraintquery.ConstraintQuery(p)
|
||||||
|
components.append(("Constraints", q))
|
||||||
|
|
||||||
if args.fsusequery or args.all:
|
if args.fsusequery or args.all:
|
||||||
if isinstance(args.fsusequery, str):
|
if isinstance(args.fsusequery, str):
|
||||||
q = setools.fsusequery.FSUseQuery(p, fs=args.fsusequery)
|
q = setools.fsusequery.FSUseQuery(p, fs=args.fsusequery)
|
||||||
|
@ -43,6 +43,9 @@ from . import mlsrulequery
|
|||||||
from . import rbacrulequery
|
from . import rbacrulequery
|
||||||
from . import terulequery
|
from . import terulequery
|
||||||
|
|
||||||
|
# Constraint queries
|
||||||
|
from . import constraintquery
|
||||||
|
|
||||||
# In-policy Context Queries
|
# In-policy Context Queries
|
||||||
from . import fsusequery
|
from . import fsusequery
|
||||||
from . import genfsconquery
|
from . import genfsconquery
|
||||||
|
78
setools/constraintquery.py
Normal file
78
setools/constraintquery.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# Copyright 2015, 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/>.
|
||||||
|
#
|
||||||
|
import re
|
||||||
|
|
||||||
|
from . import mixins
|
||||||
|
from .query import PolicyQuery
|
||||||
|
|
||||||
|
|
||||||
|
class ConstraintQuery(mixins.MatchObjClass, mixins.MatchPermission, PolicyQuery):
|
||||||
|
|
||||||
|
"""Query constraint rules (constraint/mlsconstraint)."""
|
||||||
|
|
||||||
|
def __init__(self, policy,
|
||||||
|
ruletype=[],
|
||||||
|
tclass="", tclass_regex=False,
|
||||||
|
perms=set(), perms_equal=False):
|
||||||
|
|
||||||
|
"""
|
||||||
|
Parameter:
|
||||||
|
policy The policy to query.
|
||||||
|
ruletype The rule type(s) to match.
|
||||||
|
tclass The object class(es) to match.
|
||||||
|
tclass_regex If true, use a regular expression for
|
||||||
|
matching the rule's object class.
|
||||||
|
perms The permission(s) to match.
|
||||||
|
perms_equal If true, the permission set of the rule
|
||||||
|
must exactly match the permissions
|
||||||
|
criteria. If false, any set intersection
|
||||||
|
will match.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.policy = policy
|
||||||
|
|
||||||
|
self.set_ruletype(ruletype)
|
||||||
|
self.set_tclass(tclass, regex=tclass_regex)
|
||||||
|
self.set_perms(perms, equal=perms_equal)
|
||||||
|
|
||||||
|
def results(self):
|
||||||
|
"""Generator which yields all matching constraints rules."""
|
||||||
|
|
||||||
|
for c in self.policy.constraints():
|
||||||
|
if self.ruletype:
|
||||||
|
if c.ruletype not in self.ruletype:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if self.tclass and not self._match_object_class(c.tclass):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if self.perms and not self._match_perms(c.perms):
|
||||||
|
continue
|
||||||
|
|
||||||
|
yield c
|
||||||
|
|
||||||
|
def set_ruletype(self, ruletype):
|
||||||
|
"""
|
||||||
|
Set the rule types for the rule query.
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
ruletype The rule types to match.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.ruletype = ruletype
|
@ -143,7 +143,7 @@ class SELinuxPolicy(object):
|
|||||||
@property
|
@property
|
||||||
def constraint_count(self):
|
def constraint_count(self):
|
||||||
"""The number of standard constraints."""
|
"""The number of standard constraints."""
|
||||||
return sum(1 for _ in self.constraints())
|
return sum(1 for c in self.constraints() if c.ruletype == "constrain")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dontaudit_count(self):
|
def dontaudit_count(self):
|
||||||
@ -173,12 +173,12 @@ class SELinuxPolicy(object):
|
|||||||
@property
|
@property
|
||||||
def mlsconstraint_count(self):
|
def mlsconstraint_count(self):
|
||||||
"""The number of MLS constraints."""
|
"""The number of MLS constraints."""
|
||||||
return sum(1 for _ in self.mlsconstraints())
|
return sum(1 for c in self.constraints() if c.ruletype == "mlsconstrain")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mlsvalidatetrans_count(self):
|
def mlsvalidatetrans_count(self):
|
||||||
"""The number of MLS validatetrans."""
|
"""The number of MLS validatetrans."""
|
||||||
return sum(1 for _ in self.mlsvalidatetrans())
|
return sum(1 for v in self.validatetrans() if v.ruletype == "mlsvalidatetrans")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def netifcon_count(self):
|
def netifcon_count(self):
|
||||||
@ -263,12 +263,11 @@ class SELinuxPolicy(object):
|
|||||||
@property
|
@property
|
||||||
def validatetrans_count(self):
|
def validatetrans_count(self):
|
||||||
"""The number of validatetrans."""
|
"""The number of validatetrans."""
|
||||||
return sum(1 for _ in self.validatetrans())
|
return sum(1 for v in self.validatetrans() if v.ruletype == "validatetrans")
|
||||||
|
|
||||||
#
|
#
|
||||||
# Policy components lookup functions
|
# Policy components lookup functions
|
||||||
#
|
#
|
||||||
|
|
||||||
def lookup_attribute(self, name):
|
def lookup_attribute(self, name):
|
||||||
"""Look up an attribute by name."""
|
"""Look up an attribute by name."""
|
||||||
return typeattr.attribute_factory(self.policy, name)
|
return typeattr.attribute_factory(self.policy, name)
|
||||||
@ -446,40 +445,16 @@ class SELinuxPolicy(object):
|
|||||||
#
|
#
|
||||||
|
|
||||||
def constraints(self):
|
def constraints(self):
|
||||||
"""Generator which yields all constraints."""
|
"""Generator which yields all constraints (regular and MLS)."""
|
||||||
|
|
||||||
for constraint_ in self.policy.constraint_iter():
|
for constraint_ in self.policy.constraint_iter():
|
||||||
try:
|
|
||||||
yield constraint.constraint_factory(self.policy, constraint_)
|
yield constraint.constraint_factory(self.policy, constraint_)
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def mlsconstraints(self):
|
|
||||||
"""Generator which yields all MLS constraints."""
|
|
||||||
|
|
||||||
for constraint_ in self.policy.constraint_iter():
|
|
||||||
try:
|
|
||||||
yield constraint.mlsconstraint_factory(self.policy, constraint_)
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def mlsvalidatetrans(self):
|
|
||||||
"""Generator which yields all mlsvalidatetrans."""
|
|
||||||
|
|
||||||
for validatetrans in self.policy.validatetrans_iter():
|
|
||||||
try:
|
|
||||||
yield constraint.mlsvalidatetrans_factory(self.policy, validatetrans)
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def validatetrans(self):
|
def validatetrans(self):
|
||||||
"""Generator which yields all validatetrans."""
|
"""Generator which yields all validatetrans (regular and MLS)."""
|
||||||
|
|
||||||
for validatetrans in self.policy.validatetrans_iter():
|
for validatetrans in self.policy.validatetrans_iter():
|
||||||
try:
|
|
||||||
yield constraint.validatetrans_factory(self.policy, validatetrans)
|
yield constraint.validatetrans_factory(self.policy, validatetrans)
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# In-policy Labeling statement generators
|
# In-policy Labeling statement generators
|
||||||
|
@ -35,51 +35,29 @@ def _is_mls(policy, symbol):
|
|||||||
|
|
||||||
|
|
||||||
def constraint_factory(policy, symbol):
|
def constraint_factory(policy, symbol):
|
||||||
"""Factory function for creating regular constraint objects."""
|
"""Factory function for creating constraint objects."""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if _is_mls(policy, symbol):
|
if _is_mls(policy, symbol):
|
||||||
raise TypeError("Symbol is not a constrain.")
|
return Constraint(policy, symbol, "mlsconstrain")
|
||||||
|
else:
|
||||||
|
return Constraint(policy, symbol, "constrain")
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise TypeError("Constraints cannot be looked-up.")
|
raise TypeError("Constraints cannot be looked-up.")
|
||||||
|
|
||||||
return Constraint(policy, symbol, "constrain")
|
|
||||||
|
|
||||||
|
|
||||||
def mlsconstraint_factory(policy, symbol):
|
|
||||||
"""Factory function for creating MLS constraint objects."""
|
|
||||||
|
|
||||||
try:
|
|
||||||
if not _is_mls(policy, symbol):
|
|
||||||
raise TypeError("Symbol is not a mlsconstrain.")
|
|
||||||
except AttributeError:
|
|
||||||
raise TypeError("mlsconstrain cannot be looked-up.")
|
|
||||||
|
|
||||||
return Constraint(policy, symbol, "mlsconstrain")
|
|
||||||
|
|
||||||
|
|
||||||
def validatetrans_factory(policy, symbol):
|
def validatetrans_factory(policy, symbol):
|
||||||
"""Factory function for creating regular validatetrans objects."""
|
"""Factory function for creating validatetrans objects."""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if _is_mls(policy, symbol):
|
if _is_mls(policy, symbol):
|
||||||
raise TypeError("Symbol is not a validatetrans.")
|
return Validatetrans(policy, symbol, "mlsvalidatetrans")
|
||||||
except AttributeError:
|
else:
|
||||||
raise TypeError("validatetrans cannot be looked-up.")
|
|
||||||
|
|
||||||
return Validatetrans(policy, symbol, "validatetrans")
|
return Validatetrans(policy, symbol, "validatetrans")
|
||||||
|
|
||||||
|
|
||||||
def mlsvalidatetrans_factory(policy, symbol):
|
|
||||||
"""Factory function for creating MLS validatetrans objects."""
|
|
||||||
|
|
||||||
try:
|
|
||||||
if not _is_mls(policy, symbol):
|
|
||||||
raise TypeError("Symbol is not a mlsvalidatetrans.")
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise TypeError("mlsvalidatetrans cannot be looked-up.")
|
raise TypeError("validatetrans cannot be looked-up.")
|
||||||
|
|
||||||
return Validatetrans(policy, symbol, "mlsvalidatetrans")
|
|
||||||
|
|
||||||
|
|
||||||
class BaseConstraint(symbol.PolicySymbol):
|
class BaseConstraint(symbol.PolicySymbol):
|
||||||
|
176
tests/constraintquery.conf
Normal file
176
tests/constraintquery.conf
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
class test1
|
||||||
|
class test10
|
||||||
|
class test11a
|
||||||
|
class test11b
|
||||||
|
class test11c
|
||||||
|
class test12a
|
||||||
|
class test12b
|
||||||
|
class test12c
|
||||||
|
class test20a
|
||||||
|
class test20b
|
||||||
|
class test20c
|
||||||
|
class test21a
|
||||||
|
class test21b
|
||||||
|
class test21c
|
||||||
|
|
||||||
|
sid kernel
|
||||||
|
sid security
|
||||||
|
|
||||||
|
common test
|
||||||
|
{
|
||||||
|
low_w
|
||||||
|
med_w
|
||||||
|
hi_w
|
||||||
|
low_r
|
||||||
|
med_r
|
||||||
|
hi_r
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class test1
|
||||||
|
inherits test
|
||||||
|
|
||||||
|
class test10
|
||||||
|
inherits test
|
||||||
|
|
||||||
|
class test11a
|
||||||
|
inherits test
|
||||||
|
|
||||||
|
class test11b
|
||||||
|
inherits test
|
||||||
|
|
||||||
|
class test11c
|
||||||
|
inherits test
|
||||||
|
|
||||||
|
class test12a
|
||||||
|
inherits test
|
||||||
|
|
||||||
|
class test12b
|
||||||
|
inherits test
|
||||||
|
|
||||||
|
class test12c
|
||||||
|
inherits test
|
||||||
|
|
||||||
|
class test20a
|
||||||
|
{
|
||||||
|
test20ap
|
||||||
|
test20bp
|
||||||
|
}
|
||||||
|
|
||||||
|
class test20b
|
||||||
|
{
|
||||||
|
test20ap
|
||||||
|
test20bp
|
||||||
|
}
|
||||||
|
|
||||||
|
class test20c
|
||||||
|
{
|
||||||
|
test20ap
|
||||||
|
test20bp
|
||||||
|
}
|
||||||
|
|
||||||
|
class test21a
|
||||||
|
{
|
||||||
|
test21ap
|
||||||
|
test21bp
|
||||||
|
}
|
||||||
|
|
||||||
|
class test21b
|
||||||
|
{
|
||||||
|
test21ap
|
||||||
|
test21bp
|
||||||
|
}
|
||||||
|
|
||||||
|
class test21c
|
||||||
|
{
|
||||||
|
test21ap
|
||||||
|
test21bp
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sensitivity low_s;
|
||||||
|
sensitivity medium_s alias med;
|
||||||
|
sensitivity high_s;
|
||||||
|
|
||||||
|
dominance { low_s med high_s }
|
||||||
|
|
||||||
|
category here;
|
||||||
|
category there;
|
||||||
|
category elsewhere alias lost;
|
||||||
|
|
||||||
|
level low_s:here.there;
|
||||||
|
level med:here, elsewhere;
|
||||||
|
level high_s:here.lost;
|
||||||
|
|
||||||
|
# test 1:
|
||||||
|
# ruletype: mlsconstrain
|
||||||
|
# tclass: unset
|
||||||
|
# perms: unset
|
||||||
|
mlsconstrain test1 hi_r ((l1 dom l2) or (t1 == mls_exempt));
|
||||||
|
|
||||||
|
attribute mls_exempt;
|
||||||
|
|
||||||
|
type system;
|
||||||
|
role system;
|
||||||
|
role system types system;
|
||||||
|
|
||||||
|
user system roles system level med range low_s - high_s:here.lost;
|
||||||
|
|
||||||
|
# test 10:
|
||||||
|
# ruletype: unset
|
||||||
|
# tclass: test10
|
||||||
|
# perms: unset
|
||||||
|
constrain test10 hi_w (u1 == u2);
|
||||||
|
|
||||||
|
# test 11:
|
||||||
|
# ruletype: unset
|
||||||
|
# tclass: test11a, test11b
|
||||||
|
# perms: unset
|
||||||
|
constrain test11a hi_w (u1 == u2);
|
||||||
|
constrain test11b hi_w (u1 == u2);
|
||||||
|
constrain test11c hi_w (u1 == u2);
|
||||||
|
|
||||||
|
# test 12:
|
||||||
|
# ruletype: unset
|
||||||
|
# tclass: intoflow12(a|c), regex
|
||||||
|
# perms: unset
|
||||||
|
constrain test12a hi_w (u1 == u2);
|
||||||
|
constrain test12b hi_w (u1 == u2);
|
||||||
|
constrain test12c hi_w (u1 == u2);
|
||||||
|
|
||||||
|
# test 20:
|
||||||
|
# ruletype: unset
|
||||||
|
# tclass: unset
|
||||||
|
# perms: test20ap, test20bp
|
||||||
|
constrain test20a test20ap (u1 == u2);
|
||||||
|
constrain test20b test20bp (u1 == u2);
|
||||||
|
|
||||||
|
# test 21:
|
||||||
|
# ruletype: unset
|
||||||
|
# tclass: unset
|
||||||
|
# perms: test21ap, test21bp, equal
|
||||||
|
constrain test21a test21ap (u1 == u2);
|
||||||
|
constrain test21b test21bp (u1 == u2);
|
||||||
|
constrain test21c { test21bp test21ap } (u1 == u2);
|
||||||
|
|
||||||
|
#isids
|
||||||
|
sid kernel system:system:system:medium_s:here
|
||||||
|
sid security system:system:system:high_s:lost
|
||||||
|
|
||||||
|
#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;
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
portcon tcp 80 system:object_r:system:low_s
|
||||||
|
|
||||||
|
netifcon eth0 system:object_r:system:low_s system:object_r:system:low_s
|
||||||
|
|
||||||
|
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
|
||||||
|
|
78
tests/constraintquery.py
Normal file
78
tests/constraintquery.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# Copyright 2015, 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.constraintquery import ConstraintQuery
|
||||||
|
|
||||||
|
|
||||||
|
class ConstraintQueryTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.p = SELinuxPolicy("tests/constraintquery.conf")
|
||||||
|
|
||||||
|
def test_000_unset(self):
|
||||||
|
"""Constraint query with no criteria."""
|
||||||
|
allconstraint = sorted(c.tclass for c in self.p.constraints())
|
||||||
|
|
||||||
|
q = ConstraintQuery(self.p)
|
||||||
|
qconstraint = sorted(c.tclass for c in q.results())
|
||||||
|
|
||||||
|
self.assertListEqual(allconstraint, qconstraint)
|
||||||
|
|
||||||
|
def test_001_ruletype(self):
|
||||||
|
"""Constraint query with rule type match."""
|
||||||
|
q = ConstraintQuery(self.p, ruletype=["mlsconstrain"])
|
||||||
|
|
||||||
|
constraint = sorted(c.tclass for c in q.results())
|
||||||
|
self.assertListEqual(["test1"], constraint)
|
||||||
|
|
||||||
|
def test_010_class_exact(self):
|
||||||
|
"""Constraint query with exact object class match."""
|
||||||
|
q = ConstraintQuery(self.p, tclass="test10")
|
||||||
|
|
||||||
|
constraint = sorted(c.tclass for c in q.results())
|
||||||
|
self.assertListEqual(["test10"], constraint)
|
||||||
|
|
||||||
|
def test_011_class_list(self):
|
||||||
|
"""Constraint query with object class list match."""
|
||||||
|
q = ConstraintQuery(self.p, tclass=["test11a", "test11b"])
|
||||||
|
|
||||||
|
constraint = sorted(c.tclass for c in q.results())
|
||||||
|
self.assertListEqual(["test11a", "test11b"], constraint)
|
||||||
|
|
||||||
|
def test_012_class_list(self):
|
||||||
|
"""Constraint query with object class list match."""
|
||||||
|
q = ConstraintQuery(self.p, tclass="test12(a|c)", tclass_regex=True)
|
||||||
|
|
||||||
|
constraint = sorted(c.tclass for c in q.results())
|
||||||
|
self.assertListEqual(["test12a", "test12c"], constraint)
|
||||||
|
|
||||||
|
def test_020_perms_any(self):
|
||||||
|
"""Constraint query with permission set intersection match."""
|
||||||
|
q = ConstraintQuery(self.p, perms=["test20ap", "test20bp"])
|
||||||
|
|
||||||
|
constraint = sorted(c.tclass for c in q.results())
|
||||||
|
self.assertListEqual(["test20a", "test20b"], constraint)
|
||||||
|
|
||||||
|
def test_020_perms_equal(self):
|
||||||
|
"""Constraint query with permission set equality match."""
|
||||||
|
q = ConstraintQuery(self.p, perms=["test21ap", "test21bp"], perms_equal=True)
|
||||||
|
|
||||||
|
constraint = sorted(c.tclass for c in q.results())
|
||||||
|
self.assertListEqual(["test21c"], constraint)
|
Loading…
Reference in New Issue
Block a user