mirror of
https://github.com/SELinuxProject/setools
synced 2025-03-20 01:56:31 +00:00
Initial constraints implementation.
This commit is contained in:
parent
4e995cc13f
commit
86b67ca96a
@ -50,7 +50,6 @@ import mlsrule
|
||||
|
||||
# Constraints
|
||||
import constraint
|
||||
import mlsconstraint
|
||||
|
||||
# In-policy Labeling
|
||||
import initsid
|
||||
@ -189,6 +188,26 @@ class SELinuxPolicy(object):
|
||||
# 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
|
||||
#
|
||||
|
@ -16,14 +16,205 @@
|
||||
# License along with SETools. If not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import symbol
|
||||
import string
|
||||
|
||||
import setools.qpol as qpol
|
||||
|
||||
import symbol
|
||||
import objclass
|
||||
|
||||
|
||||
class Constraint(symbol.PolicySymbol):
|
||||
|
||||
"""A constraint rule."""
|
||||
pass
|
||||
"""A constraint rule (regular or MLS)."""
|
||||
|
||||
_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):
|
||||
|
@ -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