Home | History | Annotate | Download | only in policyrep
      1 # Copyright 2014, 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 from . import exception
     20 from . import qpol
     21 from . import symbol
     22 
     23 
     24 def _symbol_lookup(qpol_policy, name):
     25     """Look up the low-level qpol policy reference"""
     26     if isinstance(name, qpol.qpol_type_t):
     27         return name
     28 
     29     try:
     30         return qpol.qpol_type_t(qpol_policy, str(name))
     31     except ValueError:
     32         raise exception.InvalidType("{0} is not a valid type/attribute".format(name))
     33 
     34 
     35 def attribute_factory(qpol_policy, name):
     36     """Factory function for creating attribute objects."""
     37 
     38     if isinstance(name, TypeAttribute):
     39         assert name.policy == qpol_policy
     40         return name
     41 
     42     qpol_symbol = _symbol_lookup(qpol_policy, name)
     43 
     44     if not qpol_symbol.isattr(qpol_policy):
     45         raise TypeError("{0} is a type".format(qpol_symbol.name(qpol_policy)))
     46 
     47     return TypeAttribute(qpol_policy, qpol_symbol)
     48 
     49 
     50 def type_factory(qpol_policy, name, deref=False):
     51     """Factory function for creating type objects."""
     52 
     53     if isinstance(name, Type):
     54         assert name.policy == qpol_policy
     55         return name
     56 
     57     qpol_symbol = _symbol_lookup(qpol_policy, name)
     58 
     59     if qpol_symbol.isattr(qpol_policy):
     60         raise TypeError("{0} is an attribute".format(qpol_symbol.name(qpol_policy)))
     61     elif qpol_symbol.isalias(qpol_policy) and not deref:
     62         raise TypeError("{0} is an alias.".format(qpol_symbol.name(qpol_policy)))
     63 
     64     return Type(qpol_policy, qpol_symbol)
     65 
     66 
     67 def type_or_attr_factory(qpol_policy, name, deref=False):
     68     """Factory function for creating type or attribute objects."""
     69 
     70     if isinstance(name, (Type, TypeAttribute)):
     71         assert name.policy == qpol_policy
     72         return name
     73 
     74     qpol_symbol = _symbol_lookup(qpol_policy, name)
     75 
     76     if qpol_symbol.isalias(qpol_policy) and not deref:
     77         raise TypeError("{0} is an alias.".format(qpol_symbol.name(qpol_policy)))
     78 
     79     if qpol_symbol.isattr(qpol_policy):
     80         return TypeAttribute(qpol_policy, qpol_symbol)
     81     else:
     82         return Type(qpol_policy, qpol_symbol)
     83 
     84 
     85 class BaseType(symbol.PolicySymbol):
     86 
     87     """Type/attribute base class."""
     88 
     89     @property
     90     def ispermissive(self):
     91         raise NotImplementedError
     92 
     93     def expand(self):
     94         """Generator that expands this attribute into its member types."""
     95         raise NotImplementedError
     96 
     97     def attributes(self):
     98         """Generator that yields all attributes for this type."""
     99         raise NotImplementedError
    100 
    101     def aliases(self):
    102         """Generator that yields all aliases for this type."""
    103         raise NotImplementedError
    104 
    105 
    106 class Type(BaseType):
    107 
    108     """A type."""
    109 
    110     @property
    111     def ispermissive(self):
    112         """(T/F) the type is permissive."""
    113         return self.qpol_symbol.ispermissive(self.policy)
    114 
    115     def expand(self):
    116         """Generator that expands this into its member types."""
    117         yield self
    118 
    119     def attributes(self):
    120         """Generator that yields all attributes for this type."""
    121         for attr in self.qpol_symbol.attr_iter(self.policy):
    122             yield attribute_factory(self.policy, attr)
    123 
    124     def aliases(self):
    125         """Generator that yields all aliases for this type."""
    126         for alias in self.qpol_symbol.alias_iter(self.policy):
    127             yield alias
    128 
    129     def statement(self):
    130         attrs = list(self.attributes())
    131         aliases = list(self.aliases())
    132         stmt = "type {0}".format(self)
    133         if aliases:
    134             if len(aliases) > 1:
    135                 stmt += " alias {{ {0} }}".format(' '.join(aliases))
    136             else:
    137                 stmt += " alias {0}".format(aliases[0])
    138         for attr in attrs:
    139             stmt += ", {0}".format(attr)
    140         stmt += ";"
    141         return stmt
    142 
    143 
    144 class TypeAttribute(BaseType):
    145 
    146     """An attribute."""
    147 
    148     def __contains__(self, other):
    149         for type_ in self.expand():
    150             if other == type_:
    151                 return True
    152 
    153         return False
    154 
    155     def expand(self):
    156         """Generator that expands this attribute into its member types."""
    157         for type_ in self.qpol_symbol.type_iter(self.policy):
    158             yield type_factory(self.policy, type_)
    159 
    160     def attributes(self):
    161         """Generator that yields all attributes for this type."""
    162         raise TypeError("{0} is an attribute, thus does not have attributes.".format(self))
    163 
    164     def aliases(self):
    165         """Generator that yields all aliases for this type."""
    166         raise TypeError("{0} is an attribute, thus does not have aliases.".format(self))
    167 
    168     @property
    169     def ispermissive(self):
    170         """(T/F) the type is permissive."""
    171         raise TypeError("{0} is an attribute, thus cannot be permissive.".format(self))
    172 
    173     def statement(self):
    174         return "attribute {0};".format(self)
    175