mirror of
https://github.com/SELinuxProject/setools
synced 2025-03-11 07:18:15 +00:00
Thoroughly test MLS representations.
Implement category and level decl. lookups along the way.
This commit is contained in:
parent
71e99abbcf
commit
4e0b7d853b
@ -50,7 +50,8 @@ int qpol_policy_get_level_by_name(const qpol_policy_t * policy, const char *name
|
||||
internal_datum = hashtab_search(db->p_levels.table, (hashtab_key_t)name);
|
||||
if (internal_datum == NULL) {
|
||||
ERR(policy, "could not find datum for level %s", name);
|
||||
errno = ENOENT;
|
||||
errno = EINVAL;
|
||||
*datum = NULL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
*datum = (qpol_level_t *) internal_datum;
|
||||
@ -339,7 +340,7 @@ int qpol_policy_get_cat_by_name(const qpol_policy_t * policy, const char *name,
|
||||
if (internal_datum == NULL) {
|
||||
*datum = NULL;
|
||||
ERR(policy, "could not find datum for cat %s", name);
|
||||
errno = ENOENT;
|
||||
errno = EINVAL;
|
||||
return STATUS_ERR;
|
||||
}
|
||||
*datum = (qpol_cat_t *) internal_datum;
|
||||
|
@ -66,6 +66,12 @@ class InvalidBoolean(InvalidSymbol):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidCategory(InvalidSymbol):
|
||||
|
||||
"""Exception for invalid MLS categories."""
|
||||
pass
|
||||
|
||||
|
||||
class InvalidClass(InvalidSymbol):
|
||||
|
||||
"""Exception for invalid object classes."""
|
||||
@ -92,6 +98,14 @@ class InvalidLevel(InvalidSymbol):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidLevelDecl(InvalidSymbol):
|
||||
|
||||
"""
|
||||
Exception for an invalid level declaration.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class InvalidRange(InvalidSymbol):
|
||||
|
||||
"""
|
||||
|
@ -52,13 +52,16 @@ def category_factory(policy, sym):
|
||||
if not enabled(policy):
|
||||
raise exception.MLSDisabled
|
||||
|
||||
if not isinstance(sym, qpol.qpol_cat_t):
|
||||
raise NotImplementedError
|
||||
if isinstance(sym, qpol.qpol_cat_t):
|
||||
if sym.isalias(policy):
|
||||
raise TypeError("{0} is an alias".format(sym.name(policy)))
|
||||
|
||||
if sym.isalias(policy):
|
||||
raise TypeError("{0} is an alias".format(sym.name(policy)))
|
||||
return Category(policy, sym)
|
||||
|
||||
return Category(policy, sym)
|
||||
try:
|
||||
return Category(policy, qpol.qpol_cat_t(policy, sym))
|
||||
except ValueError:
|
||||
raise exception.InvalidCategory("{0} is not a valid category".format(sym))
|
||||
|
||||
|
||||
def sensitivity_factory(policy, sym):
|
||||
@ -152,7 +155,7 @@ def level_decl_factory(policy, sym):
|
||||
try:
|
||||
return LevelDecl(policy, qpol.qpol_level_t(policy, sym))
|
||||
except ValueError:
|
||||
raise exception.InvalidLevel("{0} is not a valid sensitivity".format(sym))
|
||||
raise exception.InvalidLevelDecl("{0} is not a valid sensitivity".format(sym))
|
||||
|
||||
|
||||
def range_factory(policy, sym):
|
||||
@ -286,6 +289,76 @@ class BaseMLSLevel(symbol.PolicySymbol):
|
||||
|
||||
return lvl
|
||||
|
||||
@property
|
||||
def sensitivity(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def categories(self):
|
||||
"""
|
||||
Generator that yields all individual categories for this level.
|
||||
All categories are yielded, not a compact notation such as
|
||||
c0.c255
|
||||
"""
|
||||
|
||||
for cat in self.qpol_symbol.cat_iter(self.policy):
|
||||
yield category_factory(self.policy, cat)
|
||||
|
||||
|
||||
class LevelDecl(BaseMLSLevel):
|
||||
|
||||
"""
|
||||
The declaration statement for MLS levels, e.g:
|
||||
|
||||
level s7:c0.c1023;
|
||||
"""
|
||||
# below comparisons are only based on sensitivity
|
||||
# dominance since, in this context, the allowable
|
||||
# category set is being defined for the level.
|
||||
# object type is asserted here because this cannot
|
||||
# be compared to a Level instance.
|
||||
|
||||
def __eq__(self, other):
|
||||
assert not isinstance(other, Level), "Levels cannot be compared to level declarations"
|
||||
|
||||
try:
|
||||
return self.sensitivity == other.sensitivity
|
||||
except AttributeError:
|
||||
return str(self) == str(other)
|
||||
|
||||
def __ge__(self, other):
|
||||
assert not isinstance(other, Level), "Levels cannot be compared to level declarations"
|
||||
return self.sensitivity >= other.sensitivity
|
||||
|
||||
def __gt__(self, other):
|
||||
assert not isinstance(other, Level), "Levels cannot be compared to level declarations"
|
||||
return self.sensitivity > other.sensitivity
|
||||
|
||||
def __le__(self, other):
|
||||
assert not isinstance(other, Level), "Levels cannot be compared to level declarations"
|
||||
return self.sensitivity <= other.sensitivity
|
||||
|
||||
def __lt__(self, other):
|
||||
assert not isinstance(other, Level), "Levels cannot be compared to level declarations"
|
||||
return self.sensitivity < other.sensitivity
|
||||
|
||||
@property
|
||||
def sensitivity(self):
|
||||
"""The sensitivity of the level."""
|
||||
# since the qpol symbol for levels is also used for
|
||||
# MLSSensitivity objects, use self's qpol symbol
|
||||
return sensitivity_factory(self.policy, self.qpol_symbol)
|
||||
|
||||
def statement(self):
|
||||
return "level {0};".format(self)
|
||||
|
||||
|
||||
class Level(BaseMLSLevel):
|
||||
|
||||
"""An MLS level used in contexts."""
|
||||
|
||||
def __hash__(self):
|
||||
return hash(str(self))
|
||||
|
||||
def __eq__(self, other):
|
||||
try:
|
||||
othercats = set(other.categories())
|
||||
@ -323,54 +396,13 @@ class BaseMLSLevel(symbol.PolicySymbol):
|
||||
"""Incomp operator."""
|
||||
return not (self >= other or self <= other)
|
||||
|
||||
@property
|
||||
def sensitivity(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def categories(self):
|
||||
"""
|
||||
Generator that yields all individual categories for this level.
|
||||
All categories are yielded, not a compact notation such as
|
||||
c0.c255
|
||||
"""
|
||||
|
||||
for cat in self.qpol_symbol.cat_iter(self.policy):
|
||||
yield category_factory(self.policy, cat)
|
||||
|
||||
|
||||
class LevelDecl(BaseMLSLevel):
|
||||
|
||||
"""
|
||||
The declaration statement for MLS levels, e.g:
|
||||
|
||||
level s7:c0.c1023;
|
||||
"""
|
||||
|
||||
@property
|
||||
def sensitivity(self):
|
||||
"""The sensitivity of the level."""
|
||||
# since the qpol symbol for levels is also used for
|
||||
# MLSSensitivity objects, use self's qpol symbol
|
||||
return sensitivity_factory(self.policy, self.qpol_symbol)
|
||||
|
||||
def statement(self):
|
||||
return "level {0};".format(self)
|
||||
|
||||
|
||||
class Level(BaseMLSLevel):
|
||||
|
||||
"""An MLS level used in contexts."""
|
||||
|
||||
def __hash__(self):
|
||||
return hash(str(self))
|
||||
|
||||
@property
|
||||
def sensitivity(self):
|
||||
"""The sensitivity of the level."""
|
||||
return sensitivity_factory(self.policy, self.qpol_symbol.sens_name(self.policy))
|
||||
|
||||
def statement(self):
|
||||
return exception.NoStatement
|
||||
raise exception.NoStatement
|
||||
|
||||
|
||||
class Range(symbol.PolicySymbol):
|
||||
@ -392,12 +424,12 @@ class Range(symbol.PolicySymbol):
|
||||
try:
|
||||
return self.low == other.low and self.high == other.high
|
||||
except AttributeError:
|
||||
other_str = str(other)
|
||||
if "-" in other_str and " - " not in other_str:
|
||||
raise ValueError(
|
||||
"Range strings must have a spaces around the level separator (eg \"s0 - s1\")")
|
||||
|
||||
return str(self) == other_str
|
||||
# remove all spaces in the string representations
|
||||
# to handle cases where the other object does not
|
||||
# have spaces around the '-'
|
||||
other_str = str(other).replace(" ", "")
|
||||
self_str = str(self).replace(" ", "")
|
||||
return self_str == other_str
|
||||
|
||||
def __contains__(self, other):
|
||||
return self.low <= other <= self.high
|
||||
|
@ -1424,17 +1424,24 @@ typedef struct qpol_role {} qpol_role_t;
|
||||
/* qpol level */
|
||||
typedef struct qpol_level {} qpol_level_t;
|
||||
%extend qpol_level {
|
||||
%exception qpol_level {
|
||||
$action
|
||||
if (!result) {
|
||||
if (errno == EINVAL) {
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid level.");
|
||||
} else {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
qpol_level(qpol_policy_t *p, const char *name) {
|
||||
const qpol_level_t *l;
|
||||
BEGIN_EXCEPTION
|
||||
if (qpol_policy_get_level_by_name(p, name, &l)) {
|
||||
SWIG_exception(SWIG_RuntimeError, "Level does not exist");
|
||||
}
|
||||
END_EXCEPTION
|
||||
qpol_policy_get_level_by_name(p, name, &l);
|
||||
return (qpol_level_t*)l;
|
||||
fail:
|
||||
return NULL;
|
||||
};
|
||||
|
||||
~qpol_level() {
|
||||
/* no op */
|
||||
return;
|
||||
@ -1506,17 +1513,26 @@ typedef struct qpol_level {} qpol_level_t;
|
||||
/* qpol cat */
|
||||
typedef struct qpol_cat {} qpol_cat_t;
|
||||
%extend qpol_cat {
|
||||
%exception qpol_cat {
|
||||
$action
|
||||
if (!result) {
|
||||
if (errno == EINVAL) {
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid category.");
|
||||
} else {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
qpol_cat(qpol_policy_t *p, const char *name) {
|
||||
const qpol_cat_t *c;
|
||||
BEGIN_EXCEPTION
|
||||
if (qpol_policy_get_cat_by_name(p, name, &c)) {
|
||||
SWIG_exception(SWIG_RuntimeError, "Category does not exist");
|
||||
}
|
||||
END_EXCEPTION
|
||||
qpol_policy_get_cat_by_name(p, name, &c);
|
||||
return (qpol_cat_t*)c;
|
||||
fail:
|
||||
return NULL;
|
||||
};
|
||||
|
||||
~qpol_cat() {
|
||||
/* no op */
|
||||
return;
|
||||
|
@ -24,104 +24,610 @@ except ImportError:
|
||||
|
||||
from setools import SELinuxPolicy
|
||||
from setools.policyrep import qpol
|
||||
from setools.policyrep.exception import MLSDisabled, InvalidLevel, InvalidRange
|
||||
from setools.policyrep.exception import MLSDisabled, InvalidLevel, InvalidLevelDecl, InvalidRange, \
|
||||
InvalidSensitivity, InvalidCategory, NoStatement
|
||||
from setools.policyrep.mls import sensitivity_factory, category_factory, level_factory, \
|
||||
range_factory, level_decl_factory
|
||||
|
||||
|
||||
class SensitivityFactoryTest(unittest.TestCase):
|
||||
class SensitivityTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.p = SELinuxPolicy("tests/policyrep/mls.conf")
|
||||
|
||||
def mock_sens_factory(self, sens, aliases=[]):
|
||||
"""Factory function for Sensitivity objects, using a mock qpol object."""
|
||||
mock_sens = Mock(qpol.qpol_level_t)
|
||||
mock_sens.name.return_value = sens
|
||||
mock_sens.isalias.return_value = False
|
||||
mock_sens.value.return_value = int(sens[1:])
|
||||
mock_sens.alias_iter.return_value = iter(aliases)
|
||||
|
||||
return sensitivity_factory(self.p.policy, mock_sens)
|
||||
|
||||
def test_000_mls_disabled(self):
|
||||
"""Sensitivity factory on MLS-disabled policy."""
|
||||
mock_p = Mock(qpol.qpol_policy_t)
|
||||
mock_p.capability.return_value = False
|
||||
self.assertRaises(MLSDisabled, sensitivity_factory, mock_p, None)
|
||||
|
||||
def test_001_lookup(self):
|
||||
"""Sensitivity factory policy lookup."""
|
||||
sens = sensitivity_factory(self.p.policy, "s1")
|
||||
self.assertEqual("s1", sens.qpol_symbol.name(self.p.policy))
|
||||
|
||||
class CategoryFactoryTest(unittest.TestCase):
|
||||
def test_002_lookup_invalid(self):
|
||||
"""Sensitivity factory policy invalid lookup."""
|
||||
with self.assertRaises(InvalidSensitivity):
|
||||
sensitivity_factory(self.p.policy, "INVALID")
|
||||
|
||||
def test_010_string(self):
|
||||
"""Sensitivity basic string rendering."""
|
||||
sens = self.mock_sens_factory("s0")
|
||||
self.assertEqual("s0", str(sens))
|
||||
|
||||
def test_020_statement(self):
|
||||
"""Sensitivity basic statement rendering."""
|
||||
sens = self.mock_sens_factory("s0")
|
||||
self.assertEqual("sensitivity s0;", sens.statement())
|
||||
|
||||
def test_021_statement_alias(self):
|
||||
"""Sensitivity one alias statement rendering."""
|
||||
sens = self.mock_sens_factory("s0", ["name1"])
|
||||
self.assertEqual("sensitivity s0 alias name1;", sens.statement())
|
||||
|
||||
def test_022_statement_alias(self):
|
||||
"""Sensitivity two alias statement rendering."""
|
||||
sens = self.mock_sens_factory("s0", ["name1", "name2"])
|
||||
self.assertEqual("sensitivity s0 alias { name1 name2 };", sens.statement())
|
||||
|
||||
def test_030_value(self):
|
||||
"""Sensitivity value."""
|
||||
sens = self.mock_sens_factory("s17")
|
||||
self.assertEqual(17, sens._value)
|
||||
|
||||
def test_031_equal(self):
|
||||
"""Sensitivity equal."""
|
||||
sens1 = self.mock_sens_factory("s0")
|
||||
sens2 = self.mock_sens_factory("s0")
|
||||
self.assertEqual(sens1, sens2)
|
||||
|
||||
def test_032_equal_str(self):
|
||||
"""Sensitivity equal to string."""
|
||||
sens = self.mock_sens_factory("s17")
|
||||
self.assertEqual("s17", sens)
|
||||
|
||||
def test_033_not_equal(self):
|
||||
"""Sensitivity not equal."""
|
||||
sens1 = self.mock_sens_factory("s17")
|
||||
sens2 = self.mock_sens_factory("s23")
|
||||
self.assertNotEqual(sens1, sens2)
|
||||
|
||||
def test_034_not_equal_str(self):
|
||||
"""Sensitivity not equal to string."""
|
||||
sens = self.mock_sens_factory("s17")
|
||||
self.assertNotEqual("s0", sens)
|
||||
|
||||
def test_035_lt(self):
|
||||
"""Sensitivity less-than."""
|
||||
# less
|
||||
sens1 = self.mock_sens_factory("s17")
|
||||
sens2 = self.mock_sens_factory("s23")
|
||||
self.assertTrue(sens1 < sens2)
|
||||
|
||||
# equal
|
||||
sens1 = self.mock_sens_factory("s17")
|
||||
sens2 = self.mock_sens_factory("s17")
|
||||
self.assertFalse(sens1 < sens2)
|
||||
|
||||
# greater
|
||||
sens1 = self.mock_sens_factory("s17")
|
||||
sens2 = self.mock_sens_factory("s0")
|
||||
self.assertFalse(sens1 < sens2)
|
||||
|
||||
def test_036_le(self):
|
||||
"""Sensitivity less-than-or-equal."""
|
||||
# less
|
||||
sens1 = self.mock_sens_factory("s17")
|
||||
sens2 = self.mock_sens_factory("s23")
|
||||
self.assertTrue(sens1 <= sens2)
|
||||
|
||||
# equal
|
||||
sens1 = self.mock_sens_factory("s17")
|
||||
sens2 = self.mock_sens_factory("s17")
|
||||
self.assertTrue(sens1 <= sens2)
|
||||
|
||||
# greater
|
||||
sens1 = self.mock_sens_factory("s17")
|
||||
sens2 = self.mock_sens_factory("s0")
|
||||
self.assertFalse(sens1 <= sens2)
|
||||
|
||||
def test_037_ge(self):
|
||||
"""Sensitivity greater-than-or-equal."""
|
||||
# less
|
||||
sens1 = self.mock_sens_factory("s17")
|
||||
sens2 = self.mock_sens_factory("s23")
|
||||
self.assertFalse(sens1 >= sens2)
|
||||
|
||||
# equal
|
||||
sens1 = self.mock_sens_factory("s17")
|
||||
sens2 = self.mock_sens_factory("s17")
|
||||
self.assertTrue(sens1 >= sens2)
|
||||
|
||||
# greater
|
||||
sens1 = self.mock_sens_factory("s17")
|
||||
sens2 = self.mock_sens_factory("s0")
|
||||
self.assertTrue(sens1 >= sens2)
|
||||
|
||||
def test_038_gt(self):
|
||||
"""Sensitivity greater-than."""
|
||||
# less
|
||||
sens1 = self.mock_sens_factory("s17")
|
||||
sens2 = self.mock_sens_factory("s23")
|
||||
self.assertFalse(sens1 > sens2)
|
||||
|
||||
# equal
|
||||
sens1 = self.mock_sens_factory("s17")
|
||||
sens2 = self.mock_sens_factory("s17")
|
||||
self.assertFalse(sens1 > sens2)
|
||||
|
||||
# greater
|
||||
sens1 = self.mock_sens_factory("s17")
|
||||
sens2 = self.mock_sens_factory("s0")
|
||||
self.assertTrue(sens1 > sens2)
|
||||
|
||||
|
||||
class CategoryTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.p = SELinuxPolicy("tests/policyrep/mls.conf")
|
||||
|
||||
def mock_cat_factory(self, cat, aliases=[]):
|
||||
"""Factory function for Category objects, using a mock qpol object."""
|
||||
mock_cat = Mock(qpol.qpol_cat_t)
|
||||
mock_cat.name.return_value = cat
|
||||
mock_cat.isalias.return_value = False
|
||||
mock_cat.value.return_value = int(cat[1:])
|
||||
mock_cat.alias_iter.return_value = iter(aliases)
|
||||
|
||||
return category_factory(self.p.policy, mock_cat)
|
||||
|
||||
def test_000_mls_disabled(self):
|
||||
"""Category factory on MLS-disabled policy."""
|
||||
mock_p = Mock(qpol.qpol_policy_t)
|
||||
mock_p.capability.return_value = False
|
||||
self.assertRaises(MLSDisabled, category_factory, mock_p, None)
|
||||
|
||||
def test_001_lookup(self):
|
||||
"""Category factory policy lookup."""
|
||||
sens = category_factory(self.p.policy, "c1")
|
||||
self.assertEqual("c1", sens.qpol_symbol.name(self.p.policy))
|
||||
|
||||
class LevelDeclFactoryTest(unittest.TestCase):
|
||||
def test_002_lookup_invalid(self):
|
||||
"""Category factory policy invalid lookup."""
|
||||
with self.assertRaises(InvalidCategory):
|
||||
category_factory(self.p.policy, "INVALID")
|
||||
|
||||
def test_010_statement(self):
|
||||
"""Category basic string rendering."""
|
||||
cat = self.mock_cat_factory("c0")
|
||||
self.assertEqual("c0", str(cat))
|
||||
|
||||
def test_020_statement(self):
|
||||
"""Category basic statement rendering."""
|
||||
cat = self.mock_cat_factory("c0")
|
||||
self.assertEqual("category c0;", cat.statement())
|
||||
|
||||
def test_021_statement_alias(self):
|
||||
"""Category one alias statement rendering."""
|
||||
cat = self.mock_cat_factory("c0", ["name1"])
|
||||
self.assertEqual("category c0 alias name1;", cat.statement())
|
||||
|
||||
def test_022_statement_alias(self):
|
||||
"""Category two alias statement rendering."""
|
||||
cat = self.mock_cat_factory("c0", ["name1", "name2"])
|
||||
self.assertEqual("category c0 alias { name1 name2 };", cat.statement())
|
||||
|
||||
def test_030_value(self):
|
||||
"""Category value."""
|
||||
cat = self.mock_cat_factory("c17")
|
||||
self.assertEqual(17, cat._value)
|
||||
|
||||
|
||||
class LevelDeclTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.p = SELinuxPolicy("tests/policyrep/mls.conf")
|
||||
|
||||
def mock_decl_factory(self, sens, cats=[]):
|
||||
"""Factory function for LevelDecl objects, using a mock qpol object."""
|
||||
mock_decl = Mock(qpol.qpol_level_t)
|
||||
mock_decl.name.return_value = sens
|
||||
mock_decl.isalias.return_value = False
|
||||
mock_decl.value.return_value = int(sens[1:])
|
||||
mock_decl.cat_iter.return_value = iter(cats)
|
||||
|
||||
return level_decl_factory(self.p.policy, mock_decl)
|
||||
|
||||
def test_000_mls_disabled(self):
|
||||
"""Level declaration factory on MLS-disabled policy."""
|
||||
mock_p = Mock(qpol.qpol_policy_t)
|
||||
mock_p.capability.return_value = False
|
||||
self.assertRaises(MLSDisabled, level_decl_factory, mock_p, None)
|
||||
|
||||
def test_001_lookup(self):
|
||||
"""Level declaration factory policy lookup."""
|
||||
decl = level_decl_factory(self.p.policy, "s1")
|
||||
self.assertEqual("s1", decl.qpol_symbol.name(self.p.policy))
|
||||
|
||||
class LevelFactoryTest(unittest.TestCase):
|
||||
def test_002_lookup_invalid(self):
|
||||
"""Level declaration factory policy invalid lookup."""
|
||||
with self.assertRaises(InvalidLevelDecl):
|
||||
level_decl_factory(self.p.policy, "INVALID")
|
||||
|
||||
def test_010_string(self):
|
||||
"""Level declaration basic string rendering."""
|
||||
decl = self.mock_decl_factory("s0")
|
||||
self.assertEqual("s0", str(decl))
|
||||
|
||||
def test_011_string_single_cat(self):
|
||||
"""Level declaration string rendering with one category"""
|
||||
decl = self.mock_decl_factory("s0", ["c0"])
|
||||
self.assertEqual("s0:c0", str(decl))
|
||||
|
||||
def test_012_string_multiple_cat(self):
|
||||
"""Level declaration string rendering with multiple categories"""
|
||||
decl = self.mock_decl_factory("s0", ["c0", "c3"])
|
||||
self.assertEqual("s0:c0,c3", str(decl))
|
||||
|
||||
def test_013_string_cat_set(self):
|
||||
"""Level declaration string rendering with category set"""
|
||||
decl = self.mock_decl_factory("s0", ["c0", "c1", "c2", "c3"])
|
||||
self.assertEqual("s0:c0.c3", str(decl))
|
||||
|
||||
def test_014_string_complex(self):
|
||||
"""Level declaration string rendering with complex category set"""
|
||||
decl = self.mock_decl_factory("s0", ["c0", "c1", "c2", "c3", "c5", "c7", "c8", "c9"])
|
||||
self.assertEqual("s0:c0.c3,c5,c7.c9", str(decl))
|
||||
|
||||
def test_020_statement(self):
|
||||
"""Level declaration basic statement rendering."""
|
||||
decl = self.mock_decl_factory("s0")
|
||||
self.assertEqual("level s0;", decl.statement())
|
||||
|
||||
def test_021_statement_single_cat(self):
|
||||
"""Level declaration statement rendering with one category"""
|
||||
decl = self.mock_decl_factory("s0", ["c0"])
|
||||
self.assertEqual("level s0:c0;", decl.statement())
|
||||
|
||||
def test_022_statement_multiple_cat(self):
|
||||
"""Level declaration statement rendering with multiple categories"""
|
||||
decl = self.mock_decl_factory("s0", ["c0", "c3"])
|
||||
self.assertEqual("level s0:c0,c3;", decl.statement())
|
||||
|
||||
def test_012_string_cat_set(self):
|
||||
"""Level declaration statement rendering with category set"""
|
||||
decl = self.mock_decl_factory("s0", ["c0", "c1", "c2", "c3"])
|
||||
self.assertEqual("level s0:c0.c3;", decl.statement())
|
||||
|
||||
def test_013_statement_complex(self):
|
||||
"""Level declaration statement rendering with complex category set"""
|
||||
decl = self.mock_decl_factory("s0", ["c0", "c1", "c2", "c3", "c5", "c7", "c8", "c9"])
|
||||
self.assertEqual("level s0:c0.c3,c5,c7.c9;", decl.statement())
|
||||
|
||||
def test_030_equal(self):
|
||||
"""Level declaration equal."""
|
||||
decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
decl2 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
self.assertEqual(decl1, decl2)
|
||||
|
||||
def test_031_equal_str(self):
|
||||
"""Level declaration equal to string."""
|
||||
decl = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
self.assertEqual("s17:c0.c3", decl)
|
||||
|
||||
def test_032_not_equal(self):
|
||||
"""Level declaration not equal."""
|
||||
decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
decl2 = self.mock_decl_factory("s23")
|
||||
self.assertNotEqual(decl1, decl2)
|
||||
|
||||
def test_033_not_equal_str(self):
|
||||
"""Level declaration not equal to string."""
|
||||
decl = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
self.assertNotEqual("s0:c0.c2", decl)
|
||||
|
||||
def test_034_lt(self):
|
||||
"""Level declaration less-than."""
|
||||
# less
|
||||
decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"])
|
||||
self.assertTrue(decl1 < decl2)
|
||||
|
||||
# equal
|
||||
decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
decl2 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
self.assertFalse(decl1 < decl2)
|
||||
|
||||
# greater
|
||||
decl1 = self.mock_decl_factory("s24")
|
||||
decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"])
|
||||
self.assertFalse(decl1 < decl2)
|
||||
|
||||
def test_035_le(self):
|
||||
"""Level declaration less-than-or-equal."""
|
||||
# less
|
||||
decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"])
|
||||
self.assertTrue(decl1 <= decl2)
|
||||
|
||||
# equal
|
||||
decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
decl2 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
self.assertTrue(decl1 <= decl2)
|
||||
|
||||
# greater
|
||||
decl1 = self.mock_decl_factory("s24")
|
||||
decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"])
|
||||
self.assertFalse(decl1 <= decl2)
|
||||
|
||||
def test_036_ge(self):
|
||||
"""Level declaration greater-than-or-equal."""
|
||||
# less
|
||||
decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"])
|
||||
self.assertFalse(decl1 >= decl2)
|
||||
|
||||
# equal
|
||||
decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
decl2 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
self.assertTrue(decl1 >= decl2)
|
||||
|
||||
# greater
|
||||
decl1 = self.mock_decl_factory("s24")
|
||||
decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"])
|
||||
self.assertTrue(decl1 >= decl2)
|
||||
|
||||
def test_037_gt(self):
|
||||
"""Level declaration greater-than."""
|
||||
# less
|
||||
decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"])
|
||||
self.assertFalse(decl1 > decl2)
|
||||
|
||||
# equal
|
||||
decl1 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
decl2 = self.mock_decl_factory("s17", ["c0", "c1", "c2", "c3"])
|
||||
self.assertFalse(decl1 > decl2)
|
||||
|
||||
# greater
|
||||
decl1 = self.mock_decl_factory("s24")
|
||||
decl2 = self.mock_decl_factory("s23", ["c7", "c8", "c9"])
|
||||
self.assertTrue(decl1 > decl2)
|
||||
|
||||
|
||||
class LevelTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.p = SELinuxPolicy("tests/policyrep/mls.conf")
|
||||
|
||||
def mock_level_factory(self, sens, cats=[]):
|
||||
"""Factory function Level objects, using a mock qpol object."""
|
||||
mock_level = Mock(qpol.qpol_mls_level_t)
|
||||
mock_level.sens_name.return_value = sens
|
||||
mock_level.cat_iter.return_value = iter(cats)
|
||||
|
||||
return level_factory(self.p.policy, mock_level)
|
||||
|
||||
def test_000_mls_disabled(self):
|
||||
"""Level factory on MLS-disabled policy."""
|
||||
mock_p = Mock(qpol.qpol_policy_t)
|
||||
mock_p.capability.return_value = False
|
||||
self.assertRaises(MLSDisabled, level_factory, mock_p, None)
|
||||
|
||||
def test_300_level_lookup_no_cats(self):
|
||||
def test_001_lookup_no_cats(self):
|
||||
"""Level lookup with no categories."""
|
||||
levelobj = level_factory(self.p.policy, "s2")
|
||||
self.assertEqual("s2", levelobj.qpol_symbol.sens_name(self.p.policy))
|
||||
self.assertEqual(str(levelobj), "s2")
|
||||
|
||||
def test_301_level_lookup_cat_range(self):
|
||||
def test_002_lookup_cat_range(self):
|
||||
"""Level lookup with category range."""
|
||||
levelobj = level_factory(self.p.policy, "s1:c0.c13")
|
||||
self.assertEqual(str(levelobj), "s1:c0.c13")
|
||||
|
||||
def test_302_level_lookup_complex_cats(self):
|
||||
def test_003_lookup_complex_cats(self):
|
||||
"""Level lookup with complex category set."""
|
||||
levelobj = level_factory(self.p.policy, "s2:c0.c5,c7,c9.c11,c13")
|
||||
self.assertEqual(str(levelobj), "s2:c0.c5,c7,c9.c11,c13")
|
||||
|
||||
def test_303_level_lookup_bad1(self):
|
||||
def test_004_lookup_bad1(self):
|
||||
"""Level lookup with garbage."""
|
||||
self.assertRaises(InvalidLevel, level_factory, self.p.policy, "FAIL")
|
||||
|
||||
def test_304_level_lookup_bad2(self):
|
||||
def test_005_lookup_bad2(self):
|
||||
"""Level lookup with : in garbage."""
|
||||
self.assertRaises(InvalidLevel, level_factory, self.p.policy, "FAIL:BAD")
|
||||
|
||||
def test_305_level_lookup_bad_cat(self):
|
||||
def test_006_lookup_bad_cat(self):
|
||||
"""Level lookup with invalid category."""
|
||||
self.assertRaises(InvalidLevel, level_factory, self.p.policy, "s0:FAIL")
|
||||
|
||||
def test_306_level_lookup_bad_cat_range(self):
|
||||
def test_007_lookup_bad_cat_range(self):
|
||||
"""Level lookup with backwards category range."""
|
||||
self.assertRaises(InvalidLevel, level_factory, self.p.policy, "s0:c4.c0")
|
||||
|
||||
def test_306_level_lookup_cat_range_error(self):
|
||||
def test_008_lookup_cat_range_error(self):
|
||||
"""Level lookup with category range parse error."""
|
||||
self.assertRaises(InvalidLevel, level_factory, self.p.policy, "s0:c0.c2.c4")
|
||||
|
||||
def test_306_level_lookup_cat_not_assoc(self):
|
||||
def test_009_lookup_cat_not_assoc(self):
|
||||
"""Level lookup with category not associated with sensitivity."""
|
||||
# c4 is not associated with s0.
|
||||
self.assertRaises(InvalidLevel, level_factory, self.p.policy, "s0:c0,c4")
|
||||
|
||||
def test_010_equal(self):
|
||||
"""Level equal."""
|
||||
level1 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"])
|
||||
level2 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"])
|
||||
self.assertEqual(level1, level2)
|
||||
|
||||
class RangeFactoryTest(unittest.TestCase):
|
||||
def test_011_equal_str(self):
|
||||
"""Level equal to string."""
|
||||
level = self.mock_level_factory("s2", ["c0", "c1", "c2", "c3"])
|
||||
self.assertEqual("s2:c0.c3", level)
|
||||
|
||||
def test_012_not_equal(self):
|
||||
"""Level not equal."""
|
||||
level1 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"])
|
||||
level2 = self.mock_level_factory("s0")
|
||||
self.assertNotEqual(level1, level2)
|
||||
|
||||
def test_013_not_equal_str(self):
|
||||
"""Level not equal to string."""
|
||||
level = self.mock_level_factory("s0", ["c0", "c2"])
|
||||
self.assertNotEqual("s0:c0.c2", level)
|
||||
|
||||
def test_014_dom(self):
|
||||
"""Level dominate (ge)."""
|
||||
# equal
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertTrue(level1 >= level2)
|
||||
|
||||
# sens dominate
|
||||
level1 = self.mock_level_factory("s2", ["c0", "c1", "c2", "c3"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertTrue(level1 >= level2)
|
||||
|
||||
# cat set dominate
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3", "c4"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertTrue(level1 >= level2)
|
||||
|
||||
# sens domby
|
||||
level1 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertFalse(level1 >= level2)
|
||||
|
||||
# cat set domby
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertFalse(level1 >= level2)
|
||||
|
||||
# incomp
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"])
|
||||
level2 = self.mock_level_factory("s1", ["c7", "c8", "c9"])
|
||||
self.assertFalse(level1 >= level2)
|
||||
|
||||
def test_015_domby(self):
|
||||
"""Level dominate-by (le)."""
|
||||
# equal
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertTrue(level1 <= level2)
|
||||
|
||||
# sens dominate
|
||||
level1 = self.mock_level_factory("s2", ["c0", "c1", "c2", "c3"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertFalse(level1 <= level2)
|
||||
|
||||
# cat set dominate
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3", "c4"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertFalse(level1 <= level2)
|
||||
|
||||
# sens domby
|
||||
level1 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertTrue(level1 <= level2)
|
||||
|
||||
# cat set domby
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertTrue(level1 <= level2)
|
||||
|
||||
# incomp
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"])
|
||||
level2 = self.mock_level_factory("s1", ["c7", "c8", "c9"])
|
||||
self.assertFalse(level1 <= level2)
|
||||
|
||||
def test_016_proper_dom(self):
|
||||
"""Level proper dominate (gt)."""
|
||||
# equal
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertFalse(level1 > level2)
|
||||
|
||||
# sens dominate
|
||||
level1 = self.mock_level_factory("s2", ["c0", "c1", "c2", "c3"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertTrue(level1 > level2)
|
||||
|
||||
# cat set dominate
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3", "c4"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertTrue(level1 > level2)
|
||||
|
||||
# sens domby
|
||||
level1 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertFalse(level1 > level2)
|
||||
|
||||
# cat set domby
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertFalse(level1 > level2)
|
||||
|
||||
# incomp
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"])
|
||||
level2 = self.mock_level_factory("s1", ["c7", "c8", "c9"])
|
||||
self.assertFalse(level1 > level2)
|
||||
|
||||
def test_017_proper_domby(self):
|
||||
"""Level proper dominate-by (lt)."""
|
||||
# equal
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertFalse(level1 < level2)
|
||||
|
||||
# sens dominate
|
||||
level1 = self.mock_level_factory("s2", ["c0", "c1", "c2", "c3"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertFalse(level1 < level2)
|
||||
|
||||
# cat set dominate
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3", "c4"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertFalse(level1 < level2)
|
||||
|
||||
# sens domby
|
||||
level1 = self.mock_level_factory("s0", ["c0", "c1", "c2", "c3"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertTrue(level1 < level2)
|
||||
|
||||
# cat set domby
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"])
|
||||
level2 = self.mock_level_factory("s1", ["c0", "c1", "c2", "c3"])
|
||||
self.assertTrue(level1 < level2)
|
||||
|
||||
# incomp
|
||||
level1 = self.mock_level_factory("s1", ["c0", "c1", "c2"])
|
||||
level2 = self.mock_level_factory("s1", ["c7", "c8", "c9"])
|
||||
self.assertFalse(level1 < level2)
|
||||
|
||||
def test_020_level_statement(self):
|
||||
"""Level has no statement."""
|
||||
level = self.mock_level_factory("s1")
|
||||
with self.assertRaises(NoStatement):
|
||||
level.statement()
|
||||
|
||||
|
||||
class RangeTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
@ -133,41 +639,85 @@ class RangeFactoryTest(unittest.TestCase):
|
||||
mock_p.capability.return_value = False
|
||||
self.assertRaises(MLSDisabled, range_factory, mock_p, None)
|
||||
|
||||
def test_400_range_lookup_single_level(self):
|
||||
def test_001_range_lookup_single_level(self):
|
||||
"""Range lookup with single-level range."""
|
||||
rangeobj = range_factory(self.p.policy, "s0")
|
||||
self.assertEqual(str(rangeobj), "s0")
|
||||
|
||||
def test_401_range_lookup_single_level_redundant(self):
|
||||
def test_002_range_lookup_single_level_redundant(self):
|
||||
"""Range lookup with single-level range (same range listed twice)."""
|
||||
rangeobj = range_factory(self.p.policy, "s1-s1")
|
||||
self.assertEqual(str(rangeobj), "s1")
|
||||
|
||||
def test_402_range_lookup_simple(self):
|
||||
def test_003_range_lookup_simple(self):
|
||||
"""Range lookup with simple range."""
|
||||
rangeobj = range_factory(self.p.policy, "s0-s1:c0.c10")
|
||||
self.assertEqual(str(rangeobj), "s0 - s1:c0.c10")
|
||||
|
||||
def test_403_range_lookup_no_cats(self):
|
||||
def test_004_range_lookup_no_cats(self):
|
||||
"""Range lookup with no categories."""
|
||||
rangeobj = range_factory(self.p.policy, "s0-s1")
|
||||
self.assertEqual(str(rangeobj), "s0 - s1")
|
||||
|
||||
def test_404_range_lookup_complex(self):
|
||||
def test_005_range_lookup_complex(self):
|
||||
"""Range lookup with complex category set."""
|
||||
rangeobj = range_factory(self.p.policy, "s0:c0.c2-s2:c0.c5,c7,c9.c11,c13")
|
||||
self.assertEqual(str(rangeobj), "s0:c0.c2 - s2:c0.c5,c7,c9.c11,c13")
|
||||
|
||||
def test_405_range_lookup_non_dom(self):
|
||||
def test_006_range_lookup_non_dom(self):
|
||||
"""Range lookup with non-dominating high level."""
|
||||
self.assertRaises(InvalidRange, range_factory, self.p.policy, "s1-s0")
|
||||
|
||||
def test_406_range_lookup_invalid_range_low(self):
|
||||
def test_007_range_lookup_invalid_range_low(self):
|
||||
"""Range lookup with an invalid range (low)."""
|
||||
# c13 is not associated with s0.
|
||||
self.assertRaises(InvalidRange, range_factory, self.p.policy, "s0:c13-s2:c13")
|
||||
|
||||
def test_407_range_lookup_invalid_range_high(self):
|
||||
def test_008_range_lookup_invalid_range_high(self):
|
||||
"""Range lookup with an invalid range (high)."""
|
||||
# c13 is not associated with s0.
|
||||
self.assertRaises(InvalidRange, range_factory, self.p.policy, "s0-s0:c13")
|
||||
|
||||
def test_020_equal(self):
|
||||
"""Range equality."""
|
||||
rangeobj1 = range_factory(self.p.policy, "s0:c0.c2-s2:c0.c5,c7,c9.c11,c13")
|
||||
rangeobj2 = range_factory(self.p.policy, "s0:c0.c2-s2:c0.c5,c7,c9.c11,c13")
|
||||
self.assertEqual(rangeobj1, rangeobj2)
|
||||
|
||||
def test_021_equal(self):
|
||||
"""Range equal to string."""
|
||||
rangeobj = range_factory(self.p.policy, "s0:c0.c2-s2:c0.c5,c7,c9.c11,c13")
|
||||
self.assertEqual("s0:c0.c2-s2:c0.c5,c7,c9.c11,c13", rangeobj)
|
||||
self.assertEqual("s0:c0.c2- s2:c0.c5,c7,c9.c11,c13", rangeobj)
|
||||
self.assertEqual("s0:c0.c2 -s2:c0.c5,c7,c9.c11,c13", rangeobj)
|
||||
self.assertEqual("s0:c0.c2 - s2:c0.c5,c7,c9.c11,c13", rangeobj)
|
||||
|
||||
def test_022_contains(self):
|
||||
"""Range contains a level."""
|
||||
rangeobj = range_factory(self.p.policy, "s0:c1-s2:c0.c10")
|
||||
|
||||
# too low
|
||||
level1 = level_factory(self.p.policy, "s0")
|
||||
self.assertNotIn(level1, rangeobj)
|
||||
|
||||
# low level
|
||||
level2 = level_factory(self.p.policy, "s0:c1")
|
||||
self.assertIn(level2, rangeobj)
|
||||
|
||||
# mid
|
||||
level3 = level_factory(self.p.policy, "s1:c1,c5")
|
||||
self.assertIn(level3, rangeobj)
|
||||
|
||||
# high level
|
||||
level4 = level_factory(self.p.policy, "s2:c0.c10")
|
||||
self.assertIn(level4, rangeobj)
|
||||
|
||||
# too high
|
||||
level5 = level_factory(self.p.policy, "s2:c0.c11")
|
||||
self.assertNotIn(level5, rangeobj)
|
||||
|
||||
def test_030_range_statement(self):
|
||||
"""Range has no statement."""
|
||||
rangeobj = range_factory(self.p.policy, "s0")
|
||||
with self.assertRaises(NoStatement):
|
||||
rangeobj.statement()
|
||||
|
Loading…
Reference in New Issue
Block a user