Home | History | Annotate | Download | only in sepolgen
      1 # Authors: Karl MacMillan <kmacmillan (at] mentalrootkit.com>
      2 #
      3 # Copyright (C) 2006 Red Hat
      4 # see file 'COPYING' for use and warranty information
      5 #
      6 # This program is free software; you can redistribute it and/or
      7 # modify it under the terms of the GNU General Public License as
      8 # published by the Free Software Foundation; version 2 only
      9 #
     10 # This program 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 General Public License for more details.
     14 #
     15 # You should have received a copy of the GNU General Public License
     16 # along with this program; if not, write to the Free Software
     17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
     18 #
     19 
     20 """
     21 This module provides knowledge object classes and permissions. It should
     22 be used to keep this knowledge from leaking into the more generic parts of
     23 the policy generation.
     24 """
     25 
     26 # Objects that can be implicitly typed - these objects do
     27 # not _have_ to be implicitly typed (e.g., sockets can be
     28 # explicitly labeled), but they often are.
     29 #
     30 # File is in this list for /proc/self
     31 #
     32 # This list is useful when dealing with rules that have a
     33 # type (or param) used as both a subject and object. For
     34 # example:
     35 #
     36 #   allow httpd_t httpd_t : socket read;
     37 #
     38 # This rule makes sense because the socket was (presumably) created
     39 # by a process with the type httpd_t.
     40 implicitly_typed_objects = ["socket", "fd", "process", "file", "lnk_file", "fifo_file",
     41                             "dbus", "capability", "unix_stream_socket"]
     42 
     43 #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
     44 #
     45 #Information Flow
     46 #
     47 # All of the permissions in SELinux can be described in terms of
     48 # information flow. For example, a read of a file is a flow of
     49 # information from that file to the process reading. Viewing
     50 # permissions in these terms can be used to model a varity of
     51 # security properties.
     52 #
     53 # Here we have some infrastructure for understanding permissions
     54 # in terms of information flow
     55 #
     56 #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
     57 
     58 # Information flow deals with information either flowing from a subject
     59 # to and object ("write") or to a subject from an object ("read"). Read
     60 # or write is described from the subject point-of-view. It is also possible
     61 # for a permission to represent both a read and write (though the flow is
     62 # typical asymettric in terms of bandwidth). It is also possible for
     63 # permission to not flow information (meaning that the result is pure
     64 # side-effect).
     65 #
     66 # The following constants are for representing the directionality
     67 # of information flow.
     68 FLOW_NONE  = 0
     69 FLOW_READ  = 1
     70 FLOW_WRITE = 2
     71 FLOW_BOTH  = FLOW_READ | FLOW_WRITE
     72 
     73 # These are used by the parser and for nice disply of the directions
     74 str_to_dir = { "n" : FLOW_NONE, "r" : FLOW_READ, "w" : FLOW_WRITE, "b" : FLOW_BOTH }
     75 dir_to_str = { FLOW_NONE : "n", FLOW_READ : "r", FLOW_WRITE : "w", FLOW_BOTH : "b" }
     76 
     77 class PermMap:
     78     """A mapping between a permission and its information flow properties.
     79 
     80     PermMap represents the information flow properties of a single permission
     81     including the direction (read, write, etc.) and an abstract representation
     82     of the bandwidth of the flow (weight).
     83     """
     84     def __init__(self, perm, dir, weight):
     85         self.perm = perm
     86         self.dir = dir
     87         self.weight = weight
     88 
     89     def __repr__(self):
     90         return "<sepolgen.objectmodel.PermMap %s %s %d>" % (self.perm,
     91                                                            dir_to_str[self.dir],
     92                                                            self.weight)
     93 
     94 class PermMappings:
     95     """The information flow properties of a set of object classes and permissions.
     96 
     97     PermMappings maps one or more classes and permissions to their PermMap objects
     98     describing their information flow charecteristics.
     99     """
    100     def __init__(self):
    101         self.classes = { }
    102         self.default_weight = 5
    103         self.default_dir = FLOW_BOTH
    104 
    105     def from_file(self, fd):
    106         """Read the permission mappings from a file. This reads the format used
    107         by Apol in the setools suite.
    108         """
    109         # This parsing is deliberitely picky and bails at the least error. It
    110         # is assumed that the permission map file will be shipped as part
    111         # of sepolgen and not user modified, so this is a reasonable design
    112         # choice. If user supplied permission mappings are needed the parser
    113         # should be made a little more robust and give better error messages.
    114         cur = None
    115         for line in fd:
    116             fields = line.split()
    117             if len(fields) == 0 or len(fields) == 1 or fields[0] == "#":
    118                 continue
    119             if fields[0] == "class":
    120                 c = fields[1]
    121                 if c in self.classes:
    122                     raise ValueError("duplicate class in perm map")
    123                 self.classes[c] = { }
    124                 cur = self.classes[c]
    125             else:
    126                 if len(fields) != 3:
    127                     raise ValueError("error in object classs permissions")
    128                 if cur is None:
    129                     raise ValueError("permission outside of class")
    130                 pm = PermMap(fields[0], str_to_dir[fields[1]], int(fields[2]))
    131                 cur[pm.perm] = pm
    132 
    133     def get(self, obj, perm):
    134         """Get the permission map for the object permission.
    135 
    136         Returns:
    137           PermMap representing the permission
    138         Raises:
    139           KeyError if the object or permission is not defined
    140         """
    141         return self.classes[obj][perm]
    142 
    143     def getdefault(self, obj, perm):
    144         """Get the permission map for the object permission or a default.
    145 
    146         getdefault is the same as get except that a default PermMap is
    147         returned if the object class or permission is not defined. The
    148         default is FLOW_BOTH with a weight of 5.
    149         """
    150         try:
    151             pm = self.classes[obj][perm]
    152         except KeyError:
    153             return PermMap(perm, self.default_dir, self.default_weight)
    154         return pm
    155 
    156     def getdefault_direction(self, obj, perms):
    157         dir = FLOW_NONE
    158         for perm in perms:
    159             pm = self.getdefault(obj, perm)
    160             dir = dir | pm.dir
    161         return dir
    162 
    163     def getdefault_distance(self, obj, perms):
    164         total = 0
    165         for perm in perms:
    166             pm = self.getdefault(obj, perm)
    167             total += pm.weight
    168 
    169         return total
    170 
    171 
    172 
    173