summaryrefslogtreecommitdiff
path: root/lib/python2.7/site-packages/sepolgen/access.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/sepolgen/access.py')
-rw-r--r--lib/python2.7/site-packages/sepolgen/access.py332
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)