mirror of
https://github.com/SELinuxProject/setools
synced 2025-03-11 07:18:15 +00:00
Implement CommonTest and ObjClassTest.
Also fix bugs uncovered by testing.
This commit is contained in:
parent
7cb5762b4f
commit
6de35b81f7
@ -376,7 +376,7 @@ int qpol_policy_get_class_by_name(const qpol_policy_t * policy, const char *name
|
|||||||
if (internal_datum == NULL) {
|
if (internal_datum == NULL) {
|
||||||
*obj_class = NULL;
|
*obj_class = NULL;
|
||||||
ERR(policy, "could not find class %s", name);
|
ERR(policy, "could not find class %s", name);
|
||||||
errno = ENOENT;
|
errno = EINVAL;
|
||||||
return STATUS_ERR;
|
return STATUS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,7 +541,7 @@ int qpol_policy_get_common_by_name(const qpol_policy_t * policy, const char *nam
|
|||||||
if (internal_datum == NULL) {
|
if (internal_datum == NULL) {
|
||||||
*common = NULL;
|
*common = NULL;
|
||||||
ERR(policy, "could not find common %s", name);
|
ERR(policy, "could not find common %s", name);
|
||||||
errno = ENOENT;
|
errno = EINVAL;
|
||||||
return STATUS_ERR;
|
return STATUS_ERR;
|
||||||
}
|
}
|
||||||
*common = (qpol_common_t *) internal_datum;
|
*common = (qpol_common_t *) internal_datum;
|
||||||
|
@ -56,7 +56,7 @@ class Common(symbol.PolicySymbol):
|
|||||||
"""A common permission set."""
|
"""A common permission set."""
|
||||||
|
|
||||||
def __contains__(self, other):
|
def __contains__(self, other):
|
||||||
return (other in self.perms)
|
return other in self.perms
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def perms(self):
|
def perms(self):
|
||||||
@ -71,6 +71,15 @@ class ObjClass(Common):
|
|||||||
|
|
||||||
"""An object class."""
|
"""An object class."""
|
||||||
|
|
||||||
|
def __contains__(self, other):
|
||||||
|
try:
|
||||||
|
if other in self.common.perms:
|
||||||
|
return True
|
||||||
|
except exception.NoCommon:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return other in self.perms
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def common(self):
|
def common(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1942,16 +1942,24 @@ typedef struct qpol_context {} qpol_context_t;
|
|||||||
/* qpol class */
|
/* qpol class */
|
||||||
typedef struct qpol_class {} qpol_class_t;
|
typedef struct qpol_class {} qpol_class_t;
|
||||||
%extend qpol_class {
|
%extend qpol_class {
|
||||||
|
%exception qpol_class {
|
||||||
|
$action
|
||||||
|
if (!result) {
|
||||||
|
if (errno == EINVAL) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "Invalid class.");
|
||||||
|
} else {
|
||||||
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
qpol_class(qpol_policy_t *p, const char *name) {
|
qpol_class(qpol_policy_t *p, const char *name) {
|
||||||
const qpol_class_t *c;
|
const qpol_class_t *c;
|
||||||
BEGIN_EXCEPTION
|
qpol_policy_get_class_by_name(p, name, &c);
|
||||||
if (qpol_policy_get_class_by_name(p, name, &c)) {
|
|
||||||
SWIG_exception(SWIG_RuntimeError, "Class does not exist");
|
|
||||||
}
|
|
||||||
END_EXCEPTION
|
|
||||||
fail:
|
|
||||||
return (qpol_class_t*)c;
|
return (qpol_class_t*)c;
|
||||||
};
|
};
|
||||||
|
|
||||||
~qpol_class() {
|
~qpol_class() {
|
||||||
/* no op */
|
/* no op */
|
||||||
return;
|
return;
|
||||||
@ -2041,16 +2049,24 @@ typedef struct qpol_class {} qpol_class_t;
|
|||||||
/* qpol common */
|
/* qpol common */
|
||||||
typedef struct qpol_common {} qpol_common_t;
|
typedef struct qpol_common {} qpol_common_t;
|
||||||
%extend qpol_common {
|
%extend qpol_common {
|
||||||
|
%exception qpol_common {
|
||||||
|
$action
|
||||||
|
if (!result) {
|
||||||
|
if (errno == EINVAL) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "Invalid common.");
|
||||||
|
} else {
|
||||||
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
qpol_common(qpol_policy_t *p, const char *name) {
|
qpol_common(qpol_policy_t *p, const char *name) {
|
||||||
const qpol_common_t *c;
|
const qpol_common_t *c;
|
||||||
BEGIN_EXCEPTION
|
qpol_policy_get_common_by_name(p, name, &c);
|
||||||
if (qpol_policy_get_common_by_name(p, name, &c)) {
|
|
||||||
SWIG_exception(SWIG_RuntimeError, "Common does not exist");
|
|
||||||
}
|
|
||||||
END_EXCEPTION
|
|
||||||
fail:
|
|
||||||
return (qpol_common_t*)c;
|
return (qpol_common_t*)c;
|
||||||
};
|
};
|
||||||
|
|
||||||
~qpol_common() {
|
~qpol_common() {
|
||||||
/* no op */
|
/* no op */
|
||||||
return;
|
return;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#
|
#
|
||||||
from . import mls
|
from . import mls
|
||||||
from . import mlsrule
|
from . import mlsrule
|
||||||
|
from . import objclass
|
||||||
from . import polcap
|
from . import polcap
|
||||||
from . import rbacrule
|
from . import rbacrule
|
||||||
from . import role
|
from . import role
|
||||||
|
149
tests/policyrep/objclass.conf
Normal file
149
tests/policyrep/objclass.conf
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
class infoflow
|
||||||
|
class infoflow2
|
||||||
|
class infoflow3
|
||||||
|
class infoflow4
|
||||||
|
class infoflow5
|
||||||
|
class infoflow6
|
||||||
|
class infoflow7
|
||||||
|
class infoflow8
|
||||||
|
class infoflow9
|
||||||
|
class infoflow10
|
||||||
|
|
||||||
|
sid kernel
|
||||||
|
sid security
|
||||||
|
|
||||||
|
common infoflow
|
||||||
|
{
|
||||||
|
low_w
|
||||||
|
med_w
|
||||||
|
hi_w
|
||||||
|
low_r
|
||||||
|
med_r
|
||||||
|
hi_r
|
||||||
|
}
|
||||||
|
|
||||||
|
common com_a
|
||||||
|
{
|
||||||
|
hi_w
|
||||||
|
hi_r
|
||||||
|
super_r
|
||||||
|
super_w
|
||||||
|
}
|
||||||
|
|
||||||
|
common com_b
|
||||||
|
{
|
||||||
|
send
|
||||||
|
recv
|
||||||
|
}
|
||||||
|
|
||||||
|
common com_c
|
||||||
|
{
|
||||||
|
getattr
|
||||||
|
setattr
|
||||||
|
read
|
||||||
|
write
|
||||||
|
}
|
||||||
|
|
||||||
|
class infoflow
|
||||||
|
inherits infoflow
|
||||||
|
|
||||||
|
class infoflow2
|
||||||
|
inherits infoflow
|
||||||
|
{
|
||||||
|
super_w
|
||||||
|
super_r
|
||||||
|
}
|
||||||
|
|
||||||
|
class infoflow3
|
||||||
|
{
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
class infoflow4
|
||||||
|
inherits infoflow
|
||||||
|
{
|
||||||
|
super_w
|
||||||
|
super_r
|
||||||
|
super_none
|
||||||
|
super_both
|
||||||
|
super_unmapped
|
||||||
|
}
|
||||||
|
|
||||||
|
class infoflow5
|
||||||
|
inherits com_a
|
||||||
|
|
||||||
|
class infoflow6
|
||||||
|
inherits com_b
|
||||||
|
|
||||||
|
class infoflow7
|
||||||
|
inherits infoflow
|
||||||
|
{
|
||||||
|
unmapped
|
||||||
|
}
|
||||||
|
|
||||||
|
class infoflow8
|
||||||
|
{
|
||||||
|
super_w
|
||||||
|
super_r
|
||||||
|
}
|
||||||
|
|
||||||
|
class infoflow9
|
||||||
|
inherits com_c
|
||||||
|
|
||||||
|
class infoflow10
|
||||||
|
{
|
||||||
|
read
|
||||||
|
write
|
||||||
|
}
|
||||||
|
|
||||||
|
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 decl
|
||||||
|
level low_s:here.there;
|
||||||
|
level med:here, elsewhere;
|
||||||
|
level high_s:here.lost;
|
||||||
|
|
||||||
|
#some constraints
|
||||||
|
mlsconstrain infoflow hi_r ((l1 dom l2) or (t1 == mls_exempt));
|
||||||
|
|
||||||
|
attribute mls_exempt;
|
||||||
|
|
||||||
|
type system;
|
||||||
|
role system;
|
||||||
|
role system types system;
|
||||||
|
|
||||||
|
#users
|
||||||
|
user system roles system level med range low_s - high_s:here.lost;
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
175
tests/policyrep/objclass.py
Normal file
175
tests/policyrep/objclass.py
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
try:
|
||||||
|
from unittest.mock import Mock
|
||||||
|
except ImportError:
|
||||||
|
from mock import Mock
|
||||||
|
|
||||||
|
from setools import SELinuxPolicy
|
||||||
|
from setools.policyrep import qpol
|
||||||
|
from setools.policyrep.exception import InvalidCommon, InvalidClass
|
||||||
|
from setools.policyrep.objclass import common_factory, class_factory
|
||||||
|
|
||||||
|
|
||||||
|
class CommonTest(unittest.TestCase):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mock_common(name, perms):
|
||||||
|
policy = Mock(qpol.qpol_policy_t)
|
||||||
|
com = Mock(qpol.qpol_common_t)
|
||||||
|
com.name.return_value = name
|
||||||
|
com.perm_iter = lambda x: iter(perms)
|
||||||
|
return common_factory(policy, com)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.p = SELinuxPolicy("tests/policyrep/objclass.conf")
|
||||||
|
|
||||||
|
def test_001_lookup(self):
|
||||||
|
"""Common: factory policy lookup."""
|
||||||
|
com = common_factory(self.p.policy, "com_a")
|
||||||
|
self.assertEqual("com_a", com.qpol_symbol.name(self.p.policy))
|
||||||
|
|
||||||
|
def test_002_lookup_invalid(self):
|
||||||
|
"""Common: factory policy invalid lookup."""
|
||||||
|
with self.assertRaises(InvalidCommon):
|
||||||
|
common_factory(self.p.policy, "INVALID")
|
||||||
|
|
||||||
|
def test_003_lookup_object(self):
|
||||||
|
"""Common: factory policy lookup of Common object."""
|
||||||
|
com1 = common_factory(self.p.policy, "com_b")
|
||||||
|
com2 = common_factory(self.p.policy, com1)
|
||||||
|
self.assertIs(com2, com1)
|
||||||
|
|
||||||
|
def test_010_string(self):
|
||||||
|
"""Common: string representation"""
|
||||||
|
com = self.mock_common("test10", ["perm1", "perm2"])
|
||||||
|
self.assertEquals("test10", str(com))
|
||||||
|
|
||||||
|
def test_020_perms(self):
|
||||||
|
"""Common: permissions"""
|
||||||
|
com = self.mock_common("test20", ["perm1", "perm2"])
|
||||||
|
self.assertEquals(set(["perm1", "perm2"]), com.perms)
|
||||||
|
|
||||||
|
def test_030_statment(self):
|
||||||
|
"""Common: statement."""
|
||||||
|
com = self.mock_common("test30", ["perm1", "perm2"])
|
||||||
|
self.assertRegexpMatches(com.statement(), "("
|
||||||
|
"common test30\n{\n\tperm1\n\tperm2\n}"
|
||||||
|
"|"
|
||||||
|
"common test30\n{\n\tperm2\n\tperm1\n}"
|
||||||
|
")")
|
||||||
|
|
||||||
|
def test_040_contains(self):
|
||||||
|
"""Common: contains"""
|
||||||
|
com = self.mock_common("test40", ["perm1", "perm2"])
|
||||||
|
self.assertIn("perm1", com)
|
||||||
|
self.assertNotIn("perm3", com)
|
||||||
|
|
||||||
|
|
||||||
|
class ObjClassTest(unittest.TestCase):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mock_class(name, perms, com_perms=[]):
|
||||||
|
policy = Mock(qpol.qpol_policy_t)
|
||||||
|
|
||||||
|
cls = Mock(qpol.qpol_class_t)
|
||||||
|
cls.name.return_value = name
|
||||||
|
cls.perm_iter = lambda x: iter(perms)
|
||||||
|
|
||||||
|
if com_perms:
|
||||||
|
com = Mock(qpol.qpol_common_t)
|
||||||
|
com.name.return_value = name+"_common"
|
||||||
|
com.perm_iter = lambda x: iter(com_perms)
|
||||||
|
cls.common.return_value = com
|
||||||
|
else:
|
||||||
|
cls.common.side_effect = ValueError
|
||||||
|
|
||||||
|
return class_factory(policy, cls)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.p = SELinuxPolicy("tests/policyrep/objclass.conf")
|
||||||
|
|
||||||
|
def test_001_lookup(self):
|
||||||
|
"""ObjClass: factory policy lookup."""
|
||||||
|
cls = class_factory(self.p.policy, "infoflow")
|
||||||
|
self.assertEqual("infoflow", cls.qpol_symbol.name(self.p.policy))
|
||||||
|
|
||||||
|
def test_002_lookup_invalid(self):
|
||||||
|
"""ObjClass: factory policy invalid lookup."""
|
||||||
|
with self.assertRaises(InvalidClass):
|
||||||
|
class_factory(self.p.policy, "INVALID")
|
||||||
|
|
||||||
|
def test_003_lookup_object(self):
|
||||||
|
"""ObjClass: factory policy lookup of ObjClass object."""
|
||||||
|
cls1 = class_factory(self.p.policy, "infoflow4")
|
||||||
|
cls2 = class_factory(self.p.policy, cls1)
|
||||||
|
self.assertIs(cls2, cls1)
|
||||||
|
|
||||||
|
def test_010_string(self):
|
||||||
|
"""ObjClass: string representation"""
|
||||||
|
cls = self.mock_class("test10", ["perm1", "perm2"])
|
||||||
|
self.assertEquals("test10", str(cls))
|
||||||
|
|
||||||
|
def test_020_perms(self):
|
||||||
|
"""ObjClass: permissions"""
|
||||||
|
cls = self.mock_class("test20", ["perm1", "perm2"], com_perms=["perm3", "perm4"])
|
||||||
|
self.assertEquals(set(["perm1", "perm2"]), cls.perms)
|
||||||
|
|
||||||
|
def test_030_statment(self):
|
||||||
|
"""ObjClass: statement, no common."""
|
||||||
|
cls = self.mock_class("test30", ["perm1", "perm2"])
|
||||||
|
self.assertRegexpMatches(cls.statement(), "("
|
||||||
|
"class test30\n{\n\tperm1\n\tperm2\n}"
|
||||||
|
"|"
|
||||||
|
"class test30\n{\n\tperm2\n\tperm1\n}"
|
||||||
|
")")
|
||||||
|
|
||||||
|
def test_031_statment(self):
|
||||||
|
"""ObjClass: statement, with common."""
|
||||||
|
cls = self.mock_class("test31", ["perm1", "perm2"], com_perms=["perm3", "perm4"])
|
||||||
|
self.assertRegexpMatches(cls.statement(), "("
|
||||||
|
"class test31\ninherits test31_common\n{\n\tperm1\n\tperm2\n}"
|
||||||
|
"|"
|
||||||
|
"class test31\ninherits test31_common\n{\n\tperm2\n\tperm1\n}"
|
||||||
|
")")
|
||||||
|
|
||||||
|
def test_032_statment(self):
|
||||||
|
"""ObjClass: statement, with common, no class perms."""
|
||||||
|
cls = self.mock_class("test32", [], com_perms=["perm3", "perm4"])
|
||||||
|
self.assertRegexpMatches(cls.statement(), "("
|
||||||
|
"class test32\ninherits test32_common"
|
||||||
|
"|"
|
||||||
|
"class test32\ninherits test32_common"
|
||||||
|
")")
|
||||||
|
|
||||||
|
def test_040_contains(self):
|
||||||
|
"""ObjClass: contains"""
|
||||||
|
cls = self.mock_class("test40", ["perm1", "perm2"])
|
||||||
|
self.assertIn("perm1", cls)
|
||||||
|
self.assertNotIn("perm3", cls)
|
||||||
|
|
||||||
|
def test_041_contains_common(self):
|
||||||
|
"""ObjClass: contains, with common"""
|
||||||
|
cls = self.mock_class("test41", ["perm1", "perm2"], com_perms=["perm3", "perm4"])
|
||||||
|
self.assertIn("perm1", cls)
|
||||||
|
self.assertIn("perm3", cls)
|
||||||
|
self.assertNotIn("perm5", cls)
|
Loading…
Reference in New Issue
Block a user