Home | History | Annotate | Download | only in setools
      1 # Copyright 2015, Tresys Technology, LLC
      2 #
      3 # This file is part of SETools.
      4 #
      5 # SETools is free software: you can redistribute it and/or modify
      6 # it under the terms of the GNU Lesser General Public License as
      7 # published by the Free Software Foundation, either version 2.1 of
      8 # the License, or (at your option) any later version.
      9 #
     10 # SETools is distributed in the hope that it will be useful,
     11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 # GNU Lesser General Public License for more details.
     14 #
     15 # You should have received a copy of the GNU Lesser General Public
     16 # License along with SETools.  If not, see
     17 # <http://www.gnu.org/licenses/>.
     18 #
     19 import logging
     20 import re
     21 
     22 from .descriptors import CriteriaDescriptor, CriteriaSetDescriptor
     23 from .mixins import MatchObjClass, MatchPermission
     24 from .policyrep.exception import ConstraintUseError
     25 from .query import PolicyQuery
     26 from .util import match_in_set
     27 
     28 
     29 class ConstraintQuery(MatchObjClass, MatchPermission, PolicyQuery):
     30 
     31     """
     32     Query constraint rules, (mls)constrain/(mls)validatetrans.
     33 
     34     Parameter:
     35     policy            The policy to query.
     36 
     37     Keyword Parameters/Class attributes:
     38     ruletype          The list of rule type(s) to match.
     39     tclass            The object class(es) to match.
     40     tclass_regex      If true, use a regular expression for
     41                       matching the rule's object class.
     42     perms             The permission(s) to match.
     43     perms_equal       If true, the permission set of the rule
     44                       must exactly match the permissions
     45                       criteria.  If false, any set intersection
     46                       will match.
     47     perms_regex       If true, regular expression matching will be used
     48                       on the permission names instead of set logic.
     49     role              The name of the role to match in the
     50                       constraint expression.
     51     role_indirect     If true, members of an attribute will be
     52                       matched rather than the attribute itself.
     53     role_regex        If true, regular expression matching will
     54                       be used on the role.
     55     type_             The name of the type/attribute to match in the
     56                       constraint expression.
     57     type_indirect     If true, members of an attribute will be
     58                       matched rather than the attribute itself.
     59     type_regex        If true, regular expression matching will
     60                       be used on the type/attribute.
     61     user              The name of the user to match in the
     62                       constraint expression.
     63     user_regex        If true, regular expression matching will
     64                       be used on the user.
     65     """
     66 
     67     ruletype = CriteriaSetDescriptor(lookup_function="validate_constraint_ruletype")
     68     user = CriteriaDescriptor("user_regex", "lookup_user")
     69     user_regex = False
     70     role = CriteriaDescriptor("role_regex", "lookup_role")
     71     role_regex = False
     72     role_indirect = True
     73     type_ = CriteriaDescriptor("type_regex", "lookup_type_or_attr")
     74     type_regex = False
     75     type_indirect = True
     76 
     77     def __init__(self, policy, **kwargs):
     78         super(ConstraintQuery, self).__init__(policy, **kwargs)
     79         self.log = logging.getLogger(__name__)
     80 
     81     def _match_expr(self, expr, criteria, indirect, regex):
     82         """
     83         Match roles/types/users in a constraint expression,
     84         optionally by expanding the contents of attributes.
     85 
     86         Parameters:
     87         expr        The expression to match.
     88         criteria    The criteria to match.
     89         indirect    If attributes in the expression should be expanded.
     90         regex       If regular expression matching should be used.
     91         """
     92 
     93         if indirect:
     94             obj = set()
     95             for item in expr:
     96                 obj.update(item.expand())
     97         else:
     98             obj = expr
     99 
    100         return match_in_set(obj, criteria, regex)
    101 
    102     def results(self):
    103         """Generator which yields all matching constraints rules."""
    104         self.log.info("Generating constraint results from {0.policy}".format(self))
    105         self.log.debug("Ruletypes: {0.ruletype}".format(self))
    106         self._match_object_class_debug(self.log)
    107         self._match_perms_debug(self.log)
    108         self.log.debug("User: {0.user!r}, regex: {0.user_regex}".format(self))
    109         self.log.debug("Role: {0.role!r}, regex: {0.role_regex}".format(self))
    110         self.log.debug("Type: {0.type_!r}, regex: {0.type_regex}".format(self))
    111 
    112         for c in self.policy.constraints():
    113             if self.ruletype:
    114                 if c.ruletype not in self.ruletype:
    115                     continue
    116 
    117             if not self._match_object_class(c):
    118                 continue
    119 
    120             try:
    121                 if not self._match_perms(c):
    122                     continue
    123             except ConstraintUseError:
    124                     continue
    125 
    126             if self.role and not self._match_expr(
    127                         c.roles,
    128                         self.role,
    129                         self.role_indirect,
    130                         self.role_regex):
    131                     continue
    132 
    133             if self.type_ and not self._match_expr(
    134                         c.types,
    135                         self.type_,
    136                         self.type_indirect,
    137                         self.type_regex):
    138                     continue
    139 
    140             if self.user and not self._match_expr(
    141                         c.users,
    142                         self.user,
    143                         False,
    144                         self.user_regex):
    145                     continue
    146 
    147             yield c
    148