Implement part of ConstraintQuery.

Still requires criteria on the constraint expression.

closes #6
closes #12
This commit is contained in:
Chris PeBenito 2015-03-08 14:50:43 -04:00
parent a696a5a43c
commit 8812f02411
7 changed files with 360 additions and 65 deletions

7
seinfo
View File

@ -97,6 +97,13 @@ try:
q = setools.objclassquery.ObjClassQuery(p)
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 isinstance(args.fsusequery, str):
q = setools.fsusequery.FSUseQuery(p, fs=args.fsusequery)

View File

@ -43,6 +43,9 @@ from . import mlsrulequery
from . import rbacrulequery
from . import terulequery
# Constraint queries
from . import constraintquery
# In-policy Context Queries
from . import fsusequery
from . import genfsconquery

View 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

View File

@ -143,7 +143,7 @@ class SELinuxPolicy(object):
@property
def constraint_count(self):
"""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
def dontaudit_count(self):
@ -173,12 +173,12 @@ class SELinuxPolicy(object):
@property
def mlsconstraint_count(self):
"""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
def mlsvalidatetrans_count(self):
"""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
def netifcon_count(self):
@ -263,12 +263,11 @@ class SELinuxPolicy(object):
@property
def validatetrans_count(self):
"""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
#
def lookup_attribute(self, name):
"""Look up an attribute by name."""
return typeattr.attribute_factory(self.policy, name)
@ -446,40 +445,16 @@ class SELinuxPolicy(object):
#
def constraints(self):
"""Generator which yields all constraints."""
"""Generator which yields all constraints (regular and MLS)."""
for constraint_ in self.policy.constraint_iter():
try:
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
yield constraint.constraint_factory(self.policy, constraint_)
def validatetrans(self):
"""Generator which yields all validatetrans."""
"""Generator which yields all validatetrans (regular and MLS)."""
for validatetrans in self.policy.validatetrans_iter():
try:
yield constraint.validatetrans_factory(self.policy, validatetrans)
except TypeError:
pass
yield constraint.validatetrans_factory(self.policy, validatetrans)
#
# In-policy Labeling statement generators

View File

@ -35,52 +35,30 @@ def _is_mls(policy, symbol):
def constraint_factory(policy, symbol):
"""Factory function for creating regular constraint objects."""
"""Factory function for creating constraint objects."""
try:
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:
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):
"""Factory function for creating regular validatetrans objects."""
"""Factory function for creating validatetrans objects."""
try:
if _is_mls(policy, symbol):
raise TypeError("Symbol is not a validatetrans.")
return Validatetrans(policy, symbol, "mlsvalidatetrans")
else:
return Validatetrans(policy, symbol, "validatetrans")
except AttributeError:
raise TypeError("validatetrans cannot be looked-up.")
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:
raise TypeError("mlsvalidatetrans cannot be looked-up.")
return Validatetrans(policy, symbol, "mlsvalidatetrans")
class BaseConstraint(symbol.PolicySymbol):

176
tests/constraintquery.conf Normal file
View 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
View 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)