blob: 40c7197de8bad9dc15a92eb43a45954b31e2027d [file] [log] [blame]
# Copyright 2014, 2016 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/>.
#
from . import exception
from . import symbol
from . import objclass
from . import qpol
def validate_ruletype(t):
"""Validate default_* rule types."""
if t not in ["default_role", "default_range", "default_type", "default_user"]:
raise exception.InvalidDefaultType("{0} is not a valid default_* rule type.".format(t))
return t
def validate_default_value(default):
if default not in ["source", "target"]:
raise exception.InvalidDefaultValue("{0} is not a valid default_* value.".format(default))
return default
def validate_default_range(default):
if default not in ["low", "high", "low_high"]:
raise exception.InvalidDefaultRange("{0} is not a valid default_* range.".format(default))
return default
def default_factory(policy, sym):
"""Factory generator for creating default_* statement objects."""
# The low level policy groups default_* settings by object class.
# Since each class can have up to four default_* statements,
# this factory function is a generator which yields up to
# four Default objects.
if not isinstance(sym, qpol.qpol_default_object_t):
raise NotImplementedError
# qpol will essentially iterate over all classes
# and emit None for classes that don't set a default.
# Because of all of this processing, extract almost
# all of the information out of the qpol representation.
# (we have to determine almost all of it anyway)
if not sym.object_class(policy):
raise exception.NoDefaults
user = sym.user_default(policy)
role = sym.role_default(policy)
type_ = sym.type_default(policy)
range_ = sym.range_default(policy)
if user:
obj = Default(policy, sym)
obj.ruletype = "default_user"
obj.default = user
yield obj
if role:
obj = Default(policy, sym)
obj.ruletype = "default_role"
obj.default = role
yield obj
if type_:
obj = Default(policy, sym)
obj.ruletype = "default_type"
obj.default = type_
yield obj
if range_:
# range_ is something like "source low_high"
rng = range_.split()
obj = RangeDefault(policy, sym)
obj.ruletype = "default_range"
obj.default = rng[0]
obj.default_range = rng[1]
yield obj
class Default(symbol.PolicySymbol):
"""Base class for default_* statements."""
ruletype = None
default = None
def __str__(self):
return "{0.ruletype} {0.tclass} {0.default};".format(self)
def __hash__(self):
return hash("{0.ruletype}|{0.tclass}".format(self))
@property
def tclass(self):
"""The object class."""
return objclass.class_factory(self.policy, self.qpol_symbol.object_class(self.policy))
def statement(self):
return str(self)
class RangeDefault(Default):
"""A default_range statement."""
default_range = None
def __str__(self):
return "{0.ruletype} {0.tclass} {0.default} {0.default_range};".format(self)