diff options
Diffstat (limited to 'lib/python2.7/site-packages/sepolgen/access.py')
-rw-r--r-- | lib/python2.7/site-packages/sepolgen/access.py | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/lib/python2.7/site-packages/sepolgen/access.py b/lib/python2.7/site-packages/sepolgen/access.py new file mode 100644 index 0000000..a5d8698 --- /dev/null +++ b/lib/python2.7/site-packages/sepolgen/access.py @@ -0,0 +1,332 @@ +# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com> +# +# Copyright (C) 2006 Red Hat +# see file 'COPYING' for use and warranty information +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 only +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +""" +Classes representing basic access. + +SELinux - at the most basic level - represents access as +the 4-tuple subject (type or context), target (type or context), +object class, permission. The policy language elaborates this basic +access to faciliate more concise rules (e.g., allow rules can have multiple +source or target types - see refpolicy for more information). + +This module has objects for representing the most basic access (AccessVector) +and sets of that access (AccessVectorSet). These objects are used in Madison +in a variety of ways, but they are the fundamental representation of access. +""" + +from . import refpolicy +from . import util + +from selinux import audit2why + +def is_idparam(id): + """Determine if an id is a paramater in the form $N, where N is + an integer. + + Returns: + True if the id is a paramater + False if the id is not a paramater + """ + if len(id) > 1 and id[0] == '$': + try: + int(id[1:]) + except ValueError: + return False + return True + else: + return False + +class AccessVector(util.Comparison): + """ + An access vector is the basic unit of access in SELinux. + + Access vectors are the most basic representation of access within + SELinux. It represents the access a source type has to a target + type in terms of an object class and a set of permissions. + + Access vectors are distinct from AVRules in that they can only + store a single source type, target type, and object class. The + simplicity of AccessVectors makes them useful for storing access + in a form that is easy to search and compare. + + The source, target, and object are stored as string. No checking + done to verify that the strings are valid SELinux identifiers. + Identifiers in the form $N (where N is an integer) are reserved as + interface parameters and are treated as wild cards in many + circumstances. + + Properties: + .src_type - The source type allowed access. [String or None] + .tgt_type - The target type to which access is allowed. [String or None] + .obj_class - The object class to which access is allowed. [String or None] + .perms - The permissions allowed to the object class. [IdSet] + .audit_msgs - The audit messages that generated this access vector [List of strings] + """ + def __init__(self, init_list=None): + if init_list: + self.from_list(init_list) + else: + self.src_type = None + self.tgt_type = None + self.obj_class = None + self.perms = refpolicy.IdSet() + self.audit_msgs = [] + self.type = audit2why.TERULE + self.data = [] + # when implementing __eq__ also __hash__ is needed on py2 + # if object is muttable __hash__ should be None + self.__hash__ = None + + # The direction of the information flow represented by this + # access vector - used for matching + self.info_flow_dir = None + + def from_list(self, list): + """Initialize an access vector from a list. + + Initialize an access vector from a list treating the list as + positional arguments - i.e., 0 = src_type, 1 = tgt_type, etc. + All of the list elements 3 and greater are treated as perms. + For example, the list ['foo_t', 'bar_t', 'file', 'read', 'write'] + would create an access vector list with the source type 'foo_t', + target type 'bar_t', object class 'file', and permissions 'read' + and 'write'. + + This format is useful for very simple storage to strings or disc + (see to_list) and for initializing access vectors. + """ + if len(list) < 4: + raise ValueError("List must contain at least four elements %s" % str(list)) + self.src_type = list[0] + self.tgt_type = list[1] + self.obj_class = list[2] + self.perms = refpolicy.IdSet(list[3:]) + + def to_list(self): + """ + Convert an access vector to a list. + + Convert an access vector to a list treating the list as positional + values. See from_list for more information on how an access vector + is represented in a list. + """ + l = [self.src_type, self.tgt_type, self.obj_class] + l.extend(sorted(self.perms)) + return l + + def __str__(self): + return self.to_string() + + def to_string(self): + return "allow %s %s:%s %s;" % (self.src_type, self.tgt_type, + self.obj_class, self.perms.to_space_str()) + + def _compare(self, other, method): + try: + x = list(self.perms) + a = (self.src_type, self.tgt_type, self.obj_class, x) + y = list(other.perms) + x.sort() + y.sort() + b = (other.src_type, other.tgt_type, other.obj_class, y) + return method(a, b) + except (AttributeError, TypeError): + # trying to compare to foreign type + return NotImplemented + + +def avrule_to_access_vectors(avrule): + """Convert an avrule into a list of access vectors. + + AccessVectors and AVRules are similary, but differ in that + an AVRule can more than one source type, target type, and + object class. This function expands a single avrule into a + list of one or more AccessVectors representing the access + defined in the AVRule. + + + """ + if isinstance(avrule, AccessVector): + return [avrule] + a = [] + for src_type in avrule.src_types: + for tgt_type in avrule.tgt_types: + for obj_class in avrule.obj_classes: + access = AccessVector() + access.src_type = src_type + access.tgt_type = tgt_type + access.obj_class = obj_class + access.perms = avrule.perms.copy() + a.append(access) + return a + +class AccessVectorSet: + """A non-overlapping set of access vectors. + + An AccessVectorSet is designed to store one or more access vectors + that are non-overlapping. Access can be added to the set + incrementally and access vectors will be added or merged as + necessary. For example, adding the following access vectors using + add_av: + allow $1 etc_t : read; + allow $1 etc_t : write; + allow $1 var_log_t : read; + Would result in an access vector set with the access vectors: + allow $1 etc_t : { read write}; + allow $1 var_log_t : read; + """ + def __init__(self): + """Initialize an access vector set. + """ + self.src = {} + # The information flow direction of this access vector + # set - see objectmodel.py for more information. This + # stored here to speed up searching - see matching.py. + self.info_dir = None + + def __iter__(self): + """Iterate over all of the unique access vectors in the set.""" + for tgts in self.src.values(): + for objs in tgts.values(): + for av in objs.values(): + yield av + + def __len__(self): + """Return the number of unique access vectors in the set. + + Because of the inernal representation of the access vector set, + __len__ is not a constant time operation. Worst case is O(N) + where N is the number of unique access vectors, but the common + case is probably better. + """ + l = 0 + for tgts in self.src.values(): + for objs in tgts.values(): + l += len(objs) + return l + + def to_list(self): + """Return the unique access vectors in the set as a list. + + The format of the returned list is a set of nested lists, + each access vector represented by a list. This format is + designed to be simply serializable to a file. + + For example, consider an access vector set with the following + access vectors: + allow $1 user_t : file read; + allow $1 etc_t : file { read write}; + to_list would return the following: + [[$1, user_t, file, read] + [$1, etc_t, file, read, write]] + + See AccessVector.to_list for more information. + """ + l = [] + for av in self: + l.append(av.to_list()) + + return l + + def from_list(self, l): + """Add access vectors stored in a list. + + See to list for more information on the list format that this + method accepts. + + This will add all of the access from the list. Any existing + access vectors in the set will be retained. + """ + for av in l: + self.add_av(AccessVector(av)) + + def add(self, src_type, tgt_type, obj_class, perms, audit_msg=None, avc_type=audit2why.TERULE, data=[]): + """Add an access vector to the set. + """ + tgt = self.src.setdefault(src_type, { }) + cls = tgt.setdefault(tgt_type, { }) + + if (obj_class, avc_type) in cls: + access = cls[obj_class, avc_type] + else: + access = AccessVector() + access.src_type = src_type + access.tgt_type = tgt_type + access.obj_class = obj_class + access.data = data + access.type = avc_type + cls[obj_class, avc_type] = access + + access.perms.update(perms) + if audit_msg: + access.audit_msgs.append(audit_msg) + + def add_av(self, av, audit_msg=None): + """Add an access vector to the set.""" + self.add(av.src_type, av.tgt_type, av.obj_class, av.perms) + + +def avs_extract_types(avs): + types = refpolicy.IdSet() + for av in avs: + types.add(av.src_type) + types.add(av.tgt_type) + + return types + +def avs_extract_obj_perms(avs): + perms = { } + for av in avs: + if av.obj_class in perms: + s = perms[av.obj_class] + else: + s = refpolicy.IdSet() + perms[av.obj_class] = s + s.update(av.perms) + return perms + +class RoleTypeSet: + """A non-overlapping set of role type statements. + + This clas allows the incremental addition of role type statements and + maintains a non-overlapping list of statements. + """ + def __init__(self): + """Initialize an access vector set.""" + self.role_types = {} + + def __iter__(self): + """Iterate over all of the unique role allows statements in the set.""" + for role_type in self.role_types.values(): + yield role_type + + def __len__(self): + """Return the unique number of role allow statements.""" + return len(self.role_types.keys()) + + def add(self, role, type): + if role in self.role_types: + role_type = self.role_types[role] + else: + role_type = refpolicy.RoleType() + role_type.role = role + self.role_types[role] = role_type + + role_type.types.add(type) |