diff --git a/seinfo b/seinfo index 92a64fa..163086a 100755 --- a/seinfo +++ b/seinfo @@ -101,9 +101,10 @@ try: if args.constraintquery or args.all: if isinstance(args.constraintquery, str): - q = setools.constraintquery.ConstraintQuery(p, tclass=args.constraintquery) + q = setools.constraintquery.ConstraintQuery(p, tclass=args.constraintquery, + ruletype=["constrain", "mlsconstrain"]) else: - q = setools.constraintquery.ConstraintQuery(p) + q = setools.constraintquery.ConstraintQuery(p, ruletype=["constrain", "mlsconstrain"]) components.append(("Constraints", q)) if args.fsusequery or args.all: @@ -206,9 +207,12 @@ try: if args.validatetransquery or args.all: if isinstance(args.validatetransquery, str): - q = setools.validatetransquery.ValidatetransQuery(p, tclass=args.validatetransquery) + q = setools.constraintquery.ConstraintQuery(p, tclass=args.validatetransquery, + ruletype=["validatetrans", + "mlsvalidatetrans"]) else: - q = setools.validatetransquery.ValidatetransQuery(p) + q = setools.constraintquery.ConstraintQuery(p, ruletype=["validatetrans", + "mlsvalidatetrans"]) components.append(("Validatetrans", q)) if (not components or args.all) and not args.flat: diff --git a/setools/__init__.py b/setools/__init__.py index c0547ec..79dd9d6 100644 --- a/setools/__init__.py +++ b/setools/__init__.py @@ -45,7 +45,6 @@ from . import terulequery # Constraint queries from . import constraintquery -from . import validatetransquery # In-policy Context Queries from . import fsusequery diff --git a/setools/constraintquery.py b/setools/constraintquery.py index 8f5ac15..b8beb92 100644 --- a/setools/constraintquery.py +++ b/setools/constraintquery.py @@ -20,6 +20,7 @@ import re from . import mixins from .query import PolicyQuery +from .policyrep.constraint import ConstraintUseError class ConstraintQuery(mixins.MatchObjClass, mixins.MatchPermission, PolicyQuery): @@ -105,8 +106,12 @@ class ConstraintQuery(mixins.MatchObjClass, mixins.MatchPermission, PolicyQuery) if self.tclass and not self._match_object_class(c.tclass): continue - if self.perms and not self._match_perms(c.perms): - continue + if self.perms: + try: + if not self._match_perms(c.perms): + continue + except ConstraintUseError: + continue if self.role and not self._match_expr( c.roles, diff --git a/setools/policyrep/__init__.py b/setools/policyrep/__init__.py index cf733e6..cecf32c 100644 --- a/setools/policyrep/__init__.py +++ b/setools/policyrep/__init__.py @@ -177,7 +177,7 @@ class SELinuxPolicy(object): @property def mlsvalidatetrans_count(self): """The number of MLS validatetrans.""" - return sum(1 for v in self.validatetrans() if v.ruletype == "mlsvalidatetrans") + return sum(1 for v in self.constraints() if v.ruletype == "mlsvalidatetrans") @property def netifcon_count(self): @@ -262,7 +262,7 @@ class SELinuxPolicy(object): @property def validatetrans_count(self): """The number of validatetrans.""" - return sum(1 for v in self.validatetrans() if v.ruletype == "validatetrans") + return sum(1 for v in self.constraints() if v.ruletype == "validatetrans") # # Policy components lookup functions @@ -446,15 +446,11 @@ class SELinuxPolicy(object): def constraints(self): """Generator which yields all constraints (regular and MLS).""" - for constraint_ in self.policy.constraint_iter(): + for constraint_ in chain(self.policy.constraint_iter(), + self.policy.validatetrans_iter()): + yield constraint.constraint_factory(self.policy, constraint_) - def validatetrans(self): - """Generator which yields all validatetrans (regular and MLS).""" - - for validatetrans in self.policy.validatetrans_iter(): - yield constraint.validatetrans_factory(self.policy, validatetrans) - # # In-policy Labeling statement generators # diff --git a/setools/policyrep/constraint.py b/setools/policyrep/constraint.py index abdd1e6..34195ec 100644 --- a/setools/policyrep/constraint.py +++ b/setools/policyrep/constraint.py @@ -24,6 +24,12 @@ from . import typeattr from . import user +class ConstraintUseError(symbol.SymbolUseError): + + """Exception when getting permissions from a validatetrans.""" + pass + + def _is_mls(policy, symbol): # determine if this is a regular or MLS constraint/validatetrans. # this can only be determined by inspecting the expression. @@ -42,27 +48,20 @@ def constraint_factory(policy, symbol): try: if _is_mls(policy, symbol): - return Constraint(policy, symbol, "mlsconstrain") + if isinstance(symbol, qpol.qpol_constraint_t): + return Constraint(policy, symbol, "mlsconstrain") + else: + return Validatetrans(policy, symbol, "mlsvalidatetrans") else: - return Constraint(policy, symbol, "constrain") + if isinstance(symbol, qpol.qpol_constraint_t): + return Constraint(policy, symbol, "constrain") + else: + return Validatetrans(policy, symbol, "validatetrans") except AttributeError: raise TypeError("Constraints cannot be looked-up.") -def validatetrans_factory(policy, symbol): - """Factory function for creating validatetrans objects.""" - - try: - if _is_mls(policy, symbol): - return Validatetrans(policy, symbol, "mlsvalidatetrans") - else: - return Validatetrans(policy, symbol, "validatetrans") - - except AttributeError: - raise TypeError("validatetrans cannot be looked-up.") - - class BaseConstraint(symbol.PolicySymbol): """Abstract base class for constraint rules.""" @@ -229,6 +228,10 @@ class BaseConstraint(symbol.PolicySymbol): return set(self._get_symbols(role_syms, role.role_factory)) + @property + def perms(self): + raise NotImplementedError + def statement(self): return str(self) @@ -286,3 +289,7 @@ class Validatetrans(BaseConstraint): def __str__(self): return "{0.ruletype} {0.tclass}\n\t{1}\n);".format(self, self._build_expression()) + + @property + def perms(self): + raise ConstraintUseError("{0} rules do not have permissions.".format(self.ruletype)) diff --git a/setools/validatetransquery.py b/setools/validatetransquery.py deleted file mode 100644 index 709942e..0000000 --- a/setools/validatetransquery.py +++ /dev/null @@ -1,217 +0,0 @@ -# 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 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 -# . -# -import re - -from . import mixins -from .query import PolicyQuery - - -class ValidatetransQuery(mixins.MatchObjClass, PolicyQuery): - - """Query validatetrans rules (validatetrans/mlsvalidatetrans).""" - - def __init__(self, policy, - ruletype=[], - tclass="", tclass_regex=False, - role="", role_regex=False, role_indirect=True, - type_="", type_regex=False, type_indirect=True, - user="", user_regex=False): - - """ - Parameter: - policy The policy to query. - ruletype The rule type(s) to match. - tclass The object class(es) to match. - tclass_regex If true, use a regular expression for - matching the rule's object class. - role The name of the role to match in the - constraint expression. - role_indirect If true, members of an attribute will be - matched rather than the attribute itself. - role_regex If true, regular expression matching will - be used on the role. - type_ The name of the type/attribute to match in the - constraint expression. - type_indirect If true, members of an attribute will be - matched rather than the attribute itself. - type_regex If true, regular expression matching will - be used on the type/attribute. - user The name of the user to match in the - constraint expression. - user_regex If true, regular expression matching will - be used on the user. - """ - - self.policy = policy - - self.set_ruletype(ruletype) - self.set_tclass(tclass, regex=tclass_regex) - self.set_role(role, regex=role_regex, indirect=role_indirect) - self.set_type(type_, regex=type_regex, indirect=type_indirect) - self.set_user(user, regex=user_regex) - - def _match_expr(self, expr, criteria, indirect, regex): - """ - Match roles/types/users in a constraint expression, - optionally by expanding the contents of attributes. - - Parameters: - expr The expression to match. - criteria The criteria to match. - indirect If attributes in the expression should be expanded. - regex If regular expression matching should be used. - """ - - if indirect: - obj = set() - for item in expr: - obj.update(item.expand()) - else: - obj = expr - - return self._match_in_set(obj, criteria, regex) - - def results(self): - """Generator which yields all matching constraints rules.""" - - for c in self.policy.validatetrans(): - if self.ruletype: - if c.ruletype not in self.ruletype: - continue - - if self.tclass and not self._match_object_class(c.tclass): - continue - - if self.role and not self._match_expr( - c.roles, - self.role_cmp, - self.role_indirect, - self.role_regex): - continue - - if self.type_ and not self._match_expr( - c.types, - self.type_cmp, - self.type_indirect, - self.type_regex): - continue - - if self.user and not self._match_expr( - c.users, - self.user_cmp, - False, - self.user_regex): - continue - - yield c - - def set_ruletype(self, ruletype): - """ - Set the rule types for the rule query. - - Parameter: - ruletype The rule types to match. - """ - - self.ruletype = ruletype - - def set_role(self, role, **opts): - """ - Set the criteria for matching the constraint's role. - - Parameter: - role Name to match the constraint's role. - regex If true, regular expression matching will be used. - - Exceptions: - NameError Invalid keyword option. - """ - - self.role = role - - for k in list(opts.keys()): - if k == "regex": - self.role_regex = opts[k] - elif k == "indirect": - self.role_indirect = opts[k] - else: - raise NameError("Invalid name option: {0}".format(k)) - - if not self.role: - self.role_cmp = None - elif self.role_regex: - self.role_cmp = re.compile(self.role) - else: - self.role_cmp = self.policy.lookup_role(self.role) - - def set_type(self, type_, **opts): - """ - Set the criteria for matching the constraint's type. - - Parameter: - type_ Name to match the constraint's type. - regex If true, regular expression matching will be used. - - Exceptions: - NameError Invalid keyword option. - """ - - self.type_ = type_ - - for k in list(opts.keys()): - if k == "regex": - self.type_regex = opts[k] - elif k == "indirect": - self.type_indirect = opts[k] - else: - raise NameError("Invalid name option: {0}".format(k)) - - if not self.type_: - self.type_cmp = None - elif self.type_regex: - self.type_cmp = re.compile(self.type_) - else: - self.type_cmp = self.policy.lookup_type(type_) - - def set_user(self, user, **opts): - """ - Set the criteria for matching the constraint's user. - - Parameter: - user Name to match the constraint's user. - regex If true, regular expression matching will be used. - - Exceptions: - NameError Invalid keyword option. - """ - - self.user = user - - for k in list(opts.keys()): - if k == "regex": - self.user_regex = opts[k] - else: - raise NameError("Invalid name option: {0}".format(k)) - - if not self.user: - self.user_cmp = None - elif self.user_regex: - self.user_cmp = re.compile(self.user) - else: - self.user_cmp = self.policy.lookup_user(self.user) diff --git a/tests/__init__.py b/tests/__init__.py index df8b0b1..335d5a7 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -17,6 +17,7 @@ # from . import boolquery from . import categoryquery +from . import constraintquery from . import commonquery from . import dta from . import fsusequery diff --git a/tests/constraintquery.conf b/tests/constraintquery.conf index 18fef94..d206e4a 100644 --- a/tests/constraintquery.conf +++ b/tests/constraintquery.conf @@ -235,7 +235,7 @@ constrain test30 hi_w (u1 == u2 or r1 == test30r); # type: unset # user: unset constrain test31a hi_w (u1 == u2 or r1 == test31ra); -constrain test31b hi_w (u1 == u2 or r2 == test31rb); +validatetrans test31b (u1 == u2 or r2 == test31rb); # test 40: # ruletype: unset