mirror of
https://github.com/SELinuxProject/setools
synced 2025-03-23 03:26:28 +00:00
Initial constraints implementation.
This commit is contained in:
parent
4e995cc13f
commit
86b67ca96a
@ -50,7 +50,6 @@ import mlsrule
|
|||||||
|
|
||||||
# Constraints
|
# Constraints
|
||||||
import constraint
|
import constraint
|
||||||
import mlsconstraint
|
|
||||||
|
|
||||||
# In-policy Labeling
|
# In-policy Labeling
|
||||||
import initsid
|
import initsid
|
||||||
@ -189,6 +188,26 @@ class SELinuxPolicy(object):
|
|||||||
# Constraints generators
|
# Constraints generators
|
||||||
#
|
#
|
||||||
|
|
||||||
|
def constraints(self):
|
||||||
|
"""Generator which yields all constraints."""
|
||||||
|
|
||||||
|
qiter = self.policy.get_constraint_iter()
|
||||||
|
while not qiter.end():
|
||||||
|
c = constraint.Constraint(self.policy, qpol.qpol_constraint_from_void(qiter.get_item()))
|
||||||
|
if not c.ismls:
|
||||||
|
yield c
|
||||||
|
qiter.next()
|
||||||
|
|
||||||
|
def mlsconstraints(self):
|
||||||
|
"""Generator which yields all MLS constraints."""
|
||||||
|
|
||||||
|
qiter = self.policy.get_constraint_iter()
|
||||||
|
while not qiter.end():
|
||||||
|
c = constraint.Constraint(self.policy, qpol.qpol_constraint_from_void(qiter.get_item()))
|
||||||
|
if c.ismls:
|
||||||
|
yield c
|
||||||
|
qiter.next()
|
||||||
|
|
||||||
#
|
#
|
||||||
# In-policy Labeling statement generators
|
# In-policy Labeling statement generators
|
||||||
#
|
#
|
||||||
|
@ -16,14 +16,205 @@
|
|||||||
# License along with SETools. If not, see
|
# License along with SETools. If not, see
|
||||||
# <http://www.gnu.org/licenses/>.
|
# <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import symbol
|
import string
|
||||||
|
|
||||||
import setools.qpol as qpol
|
import setools.qpol as qpol
|
||||||
|
|
||||||
|
import symbol
|
||||||
|
import objclass
|
||||||
|
|
||||||
|
|
||||||
class Constraint(symbol.PolicySymbol):
|
class Constraint(symbol.PolicySymbol):
|
||||||
|
|
||||||
"""A constraint rule."""
|
"""A constraint rule (regular or MLS)."""
|
||||||
pass
|
|
||||||
|
_expr_type_to_text = {
|
||||||
|
qpol.QPOL_CEXPR_TYPE_NOT: "not",
|
||||||
|
qpol.QPOL_CEXPR_TYPE_AND: "and",
|
||||||
|
qpol.QPOL_CEXPR_TYPE_OR: "\n\tor"}
|
||||||
|
|
||||||
|
_expr_op_to_text = {
|
||||||
|
qpol.QPOL_CEXPR_OP_EQ: "==",
|
||||||
|
qpol.QPOL_CEXPR_OP_NEQ: "!=",
|
||||||
|
qpol.QPOL_CEXPR_OP_DOM: "dom",
|
||||||
|
qpol.QPOL_CEXPR_OP_DOMBY: "domby",
|
||||||
|
qpol.QPOL_CEXPR_OP_INCOMP: "incomp"}
|
||||||
|
|
||||||
|
_sym_to_text = {
|
||||||
|
qpol.QPOL_CEXPR_SYM_USER: "u1",
|
||||||
|
qpol.QPOL_CEXPR_SYM_ROLE: "r1",
|
||||||
|
qpol.QPOL_CEXPR_SYM_TYPE: "t1",
|
||||||
|
qpol.QPOL_CEXPR_SYM_USER + qpol.QPOL_CEXPR_SYM_TARGET: "u2",
|
||||||
|
qpol.QPOL_CEXPR_SYM_ROLE + qpol.QPOL_CEXPR_SYM_TARGET: "r2",
|
||||||
|
qpol.QPOL_CEXPR_SYM_TYPE + qpol.QPOL_CEXPR_SYM_TARGET: "t2",
|
||||||
|
qpol.QPOL_CEXPR_SYM_L1L2: "l1",
|
||||||
|
qpol.QPOL_CEXPR_SYM_L1H2: "l1",
|
||||||
|
qpol.QPOL_CEXPR_SYM_H1L2: "h1",
|
||||||
|
qpol.QPOL_CEXPR_SYM_H1H2: "h1",
|
||||||
|
qpol.QPOL_CEXPR_SYM_L1H1: "l1",
|
||||||
|
qpol.QPOL_CEXPR_SYM_L2H2: "l2",
|
||||||
|
qpol.QPOL_CEXPR_SYM_L1L2 + qpol.QPOL_CEXPR_SYM_TARGET: "l2",
|
||||||
|
qpol.QPOL_CEXPR_SYM_L1H2 + qpol.QPOL_CEXPR_SYM_TARGET: "h2",
|
||||||
|
qpol.QPOL_CEXPR_SYM_H1L2 + qpol.QPOL_CEXPR_SYM_TARGET: "l2",
|
||||||
|
qpol.QPOL_CEXPR_SYM_H1H2 + qpol.QPOL_CEXPR_SYM_TARGET: "h2",
|
||||||
|
qpol.QPOL_CEXPR_SYM_L1H1 + qpol.QPOL_CEXPR_SYM_TARGET: "h1",
|
||||||
|
qpol.QPOL_CEXPR_SYM_L2H2 + qpol.QPOL_CEXPR_SYM_TARGET: "h2"}
|
||||||
|
|
||||||
|
_expr_type_to_precedence = {
|
||||||
|
qpol.QPOL_CEXPR_TYPE_NOT: 3,
|
||||||
|
qpol.QPOL_CEXPR_TYPE_AND: 2,
|
||||||
|
qpol.QPOL_CEXPR_TYPE_OR: 1}
|
||||||
|
|
||||||
|
# all operators have the same precedence
|
||||||
|
_expr_op_precedence = 4
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.ismls:
|
||||||
|
rule_string = "mlsconstrain {0.tclass} ".format(self)
|
||||||
|
else:
|
||||||
|
rule_string = "constrain {0.tclass} ".format(self)
|
||||||
|
|
||||||
|
perms = self.perms
|
||||||
|
if len(perms) > 1:
|
||||||
|
rule_string += "{{ {0} }} (\n".format(string.join(perms))
|
||||||
|
else:
|
||||||
|
# convert to list since sets cannot be indexed
|
||||||
|
rule_string += "{0} (\n".format(list(perms)[0])
|
||||||
|
|
||||||
|
rule_string += "\t{0}\n);".format(self.__build_expression())
|
||||||
|
|
||||||
|
return rule_string
|
||||||
|
|
||||||
|
def __build_expression(self):
|
||||||
|
# qpol representation is in postfix notation. This code
|
||||||
|
# converts it to infix notation. Parentheses are added
|
||||||
|
# to ensure correct expressions, though they may end up
|
||||||
|
# being overused. Set previous operator at start to the
|
||||||
|
# highest precedence (op) so if there is a single binary
|
||||||
|
# operator, no parentheses are output
|
||||||
|
|
||||||
|
expr_string = ""
|
||||||
|
qpol_iter = self.qpol_symbol.get_expr_iter(self.policy)
|
||||||
|
|
||||||
|
stack = []
|
||||||
|
prev_oper = self._expr_op_precedence
|
||||||
|
while not qpol_iter.end():
|
||||||
|
expr_node = qpol.qpol_constraint_expr_node_from_void(
|
||||||
|
qpol_iter.get_item())
|
||||||
|
|
||||||
|
op = expr_node.get_op(self.policy)
|
||||||
|
sym_type = expr_node.get_sym_type(self.policy)
|
||||||
|
expr_type = expr_node.get_expr_type(self.policy)
|
||||||
|
|
||||||
|
if expr_type == qpol.QPOL_CEXPR_TYPE_ATTR:
|
||||||
|
stack.append([self._sym_to_text[sym_type],
|
||||||
|
self._expr_op_to_text[op],
|
||||||
|
self._sym_to_text[sym_type + qpol.QPOL_CEXPR_SYM_TARGET]])
|
||||||
|
prev_oper = self._expr_op_precedence
|
||||||
|
elif expr_type == qpol.QPOL_CEXPR_TYPE_NAMES:
|
||||||
|
names = []
|
||||||
|
names_iter = expr_node.get_names_iter(self.policy)
|
||||||
|
while not names_iter.end():
|
||||||
|
names.append(qpol.to_str(names_iter.get_item()))
|
||||||
|
names_iter.next()
|
||||||
|
|
||||||
|
if not names:
|
||||||
|
names_str = "<empty set>"
|
||||||
|
elif len(names) == 1:
|
||||||
|
names_str = names[0]
|
||||||
|
else:
|
||||||
|
names_str = "{{ {0} }}".format(string.join(names))
|
||||||
|
|
||||||
|
stack.append([self._sym_to_text[sym_type],
|
||||||
|
self._expr_op_to_text[op],
|
||||||
|
names_str])
|
||||||
|
prev_oper = self._expr_op_precedence
|
||||||
|
elif expr_type == qpol.QPOL_CEXPR_TYPE_NOT:
|
||||||
|
# unary operator
|
||||||
|
operand = stack.pop()
|
||||||
|
stack.append([self._expr_type_to_text[expr_type],
|
||||||
|
"(",
|
||||||
|
operand,
|
||||||
|
")"])
|
||||||
|
prev_oper = self._expr_type_to_precedence[expr_type]
|
||||||
|
else:
|
||||||
|
operand1 = stack.pop()
|
||||||
|
operand2 = stack.pop()
|
||||||
|
|
||||||
|
# if previous operator is of higher precedence
|
||||||
|
# no parentheses are needed.
|
||||||
|
if self._expr_type_to_precedence[expr_type] < prev_oper:
|
||||||
|
stack.append([operand1,
|
||||||
|
self._expr_type_to_text[expr_type],
|
||||||
|
operand2])
|
||||||
|
else:
|
||||||
|
stack.append(["(",
|
||||||
|
operand1,
|
||||||
|
self._expr_type_to_text[expr_type],
|
||||||
|
operand2,
|
||||||
|
")"])
|
||||||
|
|
||||||
|
prev_oper = self._expr_type_to_precedence[expr_type]
|
||||||
|
|
||||||
|
qpol_iter.next()
|
||||||
|
|
||||||
|
return self.__unwind_subexpression(stack)
|
||||||
|
|
||||||
|
def __unwind_subexpression(self, expr):
|
||||||
|
ret = []
|
||||||
|
|
||||||
|
# do a string.join on sublists (subexpressions)
|
||||||
|
for i in expr:
|
||||||
|
if isinstance(i, list):
|
||||||
|
ret.append(self.__unwind_subexpression(i))
|
||||||
|
else:
|
||||||
|
ret.append(i)
|
||||||
|
|
||||||
|
return string.join(ret)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ismls(self):
|
||||||
|
try:
|
||||||
|
return self._ismls
|
||||||
|
except AttributeError:
|
||||||
|
self._ismls = False
|
||||||
|
|
||||||
|
qpol_iter = self.qpol_symbol.get_expr_iter(self.policy)
|
||||||
|
while not qpol_iter.end():
|
||||||
|
expr_node = qpol.qpol_constraint_expr_node_from_void(
|
||||||
|
qpol_iter.get_item())
|
||||||
|
|
||||||
|
sym_type = expr_node.get_sym_type(self.policy)
|
||||||
|
expr_type = expr_node.get_expr_type(self.policy)
|
||||||
|
|
||||||
|
if expr_type == qpol.QPOL_CEXPR_TYPE_ATTR and sym_type >= qpol.QPOL_CEXPR_SYM_L1L2:
|
||||||
|
self._ismls = True
|
||||||
|
break
|
||||||
|
|
||||||
|
qpol_iter.next()
|
||||||
|
|
||||||
|
return self._ismls
|
||||||
|
|
||||||
|
@property
|
||||||
|
def perms(self):
|
||||||
|
"""The constraint's permission set."""
|
||||||
|
|
||||||
|
iter = self.qpol_symbol.get_perm_iter(self.policy)
|
||||||
|
|
||||||
|
p = set()
|
||||||
|
while not iter.end():
|
||||||
|
p.add(qpol.to_str(iter.get_item()))
|
||||||
|
iter.next()
|
||||||
|
|
||||||
|
return p
|
||||||
|
|
||||||
|
def statement(self):
|
||||||
|
return str(self)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tclass(self):
|
||||||
|
"""Object class for this constraint."""
|
||||||
|
return objclass.ObjClass(self.policy, self.qpol_symbol.get_class(self.policy))
|
||||||
|
|
||||||
|
|
||||||
class ValidateTrans(symbol.PolicySymbol):
|
class ValidateTrans(symbol.PolicySymbol):
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
# Copyright 2014, 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 constraint
|
|
||||||
import setools.qpol as qpol
|
|
||||||
|
|
||||||
|
|
||||||
class MLSConstraint(constraint.Constraint):
|
|
||||||
|
|
||||||
"""An MLS constraint rule."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class MLSValidateTrans(constraint.ValidateTrans):
|
|
||||||
|
|
||||||
"""An MLS validate transition rule."""
|
|
||||||
pass
|
|
Loading…
Reference in New Issue
Block a user