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 . import mixins, query
     23 from .descriptors import CriteriaDescriptor, CriteriaSetDescriptor, RuletypeDescriptor
     24 from .policyrep.exception import ConstraintUseError
     25 
     26 
     27 class ConstraintQuery(mixins.MatchObjClass, mixins.MatchPermission, query.PolicyQuery):
     28 
     29     """
     30     Query constraint rules, (mls)constrain/(mls)validatetrans.
     31 
     32     Parameter:
     33     policy            The policy to query.
     34 
     35     Keyword Parameters/Class attributes:
     36     ruletype          The list of rule type(s) to match.
     37     tclass            The object class(es) to match.
     38     tclass_regex      If true, use a regular expression for
     39                       matching the rule's object class.
     40     perms             The permission(s) to match.
     41     perms_equal       If true, the permission set of the rule
     42                       must exactly match the permissions
     43                       criteria.  If false, any set intersection
     44                       will match.
     45     perms_regex       If true, regular expression matching will be used
     46                       on the permission names instead of set logic.
     47     role              The name of the role to match in the
     48                       constraint expression.
     49     role_indirect     If true, members of an attribute will be
     50                       matched rather than the attribute itself.
     51     role_regex        If true, regular expression matching will
     52                       be used on the role.
     53     type_             The name of the type/attribute to match in the
     54                       constraint expression.
     55     type_indirect     If true, members of an attribute will be
     56                       matched rather than the attribute itself.
     57     type_regex        If true, regular expression matching will
     58                       be used on the type/attribute.
     59     user              The name of the user to match in the
     60                       constraint expression.
     61     user_regex        If true, regular expression matching will
     62                       be used on the user.
     63     """
     64 
     65     ruletype = RuletypeDescriptor("validate_constraint_ruletype")
     66     user = CriteriaDescriptor("user_regex", "lookup_user")
     67     user_regex = False
     68     role = CriteriaDescriptor("role_regex", "lookup_role")
     69     role_regex = False
     70     role_indirect = True
     71     type_ = CriteriaDescriptor("type_regex", "lookup_type_or_attr")
     72     type_regex = False
     73     type_indirect = True
     74 
     75     def _match_expr(self, expr, criteria, indirect, regex):
     76         """
     77         Match roles/types/users in a constraint expression,
     78         optionally by expanding the contents of attributes.
     79 
     80         Parameters:
     81         expr        The expression to match.
     82         criteria    The criteria to match.
     83         indirect    If attributes in the expression should be expanded.
     84         regex       If regular expression matching should be used.
     85         """
     86 
     87         if indirect:
     88             obj = set()
     89             for item in expr:
     90                 obj.update(item.expand())
     91         else:
     92             obj = expr
     93 
     94         return self._match_in_set(obj, criteria, regex)
     95 
     96     def results(self):
     97         """Generator which yields all matching constraints rules."""
     98         self.log.info("Generating results from {0.policy}".format(self))
     99         self.log.debug("Ruletypes: {0.ruletype}".format(self))
    100         self.log.debug("Class: {0.tclass!r}, regex: {0.tclass_regex}".format(self))
    101         self.log.debug("Perms: {0.perms!r}, regex: {0.perms_regex}, eq: {0.perms_equal}".
    102                        format(self))
    103         self.log.debug("User: {0.user!r}, regex: {0.user_regex}".format(self))
    104         self.log.debug("Role: {0.role!r}, regex: {0.role_regex}".format(self))
    105         self.log.debug("Type: {0.type_!r}, regex: {0.type_regex}".format(self))
    106 
    107         for c in self.policy.constraints():
    108             if self.ruletype:
    109                 if c.ruletype not in self.ruletype:
    110                     continue
    111 
    112             if not self._match_object_class(c):
    113                 continue
    114 
    115             try:
    116                 if not self._match_perms(c):
    117                     continue
    118             except ConstraintUseError:
    119                     continue
    120 
    121             if self.role and not self._match_expr(
    122                         c.roles,
    123                         self.role,
    124                         self.role_indirect,
    125                         self.role_regex):
    126                     continue
    127 
    128             if self.type_ and not self._match_expr(
    129                         c.types,
    130                         self.type_,
    131                         self.type_indirect,
    132                         self.type_regex):
    133                     continue
    134 
    135             if self.user and not self._match_expr(
    136                         c.users,
    137                         self.user,
    138                         False,
    139                         self.user_regex):
    140                     continue
    141 
    142             yield c
    143