Implement CommonTest and ObjClassTest.

Also fix bugs uncovered by testing.
This commit is contained in:
Chris PeBenito 2015-04-23 11:04:37 -04:00
parent 7cb5762b4f
commit 6de35b81f7
6 changed files with 365 additions and 15 deletions

View File

@ -376,7 +376,7 @@ int qpol_policy_get_class_by_name(const qpol_policy_t * policy, const char *name
if (internal_datum == NULL) {
*obj_class = NULL;
ERR(policy, "could not find class %s", name);
errno = ENOENT;
errno = EINVAL;
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) {
*common = NULL;
ERR(policy, "could not find common %s", name);
errno = ENOENT;
errno = EINVAL;
return STATUS_ERR;
}
*common = (qpol_common_t *) internal_datum;

View File

@ -56,7 +56,7 @@ class Common(symbol.PolicySymbol):
"""A common permission set."""
def __contains__(self, other):
return (other in self.perms)
return other in self.perms
@property
def perms(self):
@ -71,6 +71,15 @@ class ObjClass(Common):
"""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
def common(self):
"""

View File

@ -1942,16 +1942,24 @@ typedef struct qpol_context {} qpol_context_t;
/* qpol class */
typedef struct qpol_class {} qpol_class_t;
%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) {
const qpol_class_t *c;
BEGIN_EXCEPTION
if (qpol_policy_get_class_by_name(p, name, &c)) {
SWIG_exception(SWIG_RuntimeError, "Class does not exist");
}
END_EXCEPTION
fail:
qpol_policy_get_class_by_name(p, name, &c);
return (qpol_class_t*)c;
};
~qpol_class() {
/* no op */
return;
@ -2041,16 +2049,24 @@ typedef struct qpol_class {} qpol_class_t;
/* qpol common */
typedef struct qpol_common {} qpol_common_t;
%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) {
const qpol_common_t *c;
BEGIN_EXCEPTION
if (qpol_policy_get_common_by_name(p, name, &c)) {
SWIG_exception(SWIG_RuntimeError, "Common does not exist");
}
END_EXCEPTION
fail:
qpol_policy_get_common_by_name(p, name, &c);
return (qpol_common_t*)c;
};
~qpol_common() {
/* no op */
return;

View File

@ -17,6 +17,7 @@
#
from . import mls
from . import mlsrule
from . import objclass
from . import polcap
from . import rbacrule
from . import role

View 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
View 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)