diff --git a/libapol/__init__.py b/libapol/__init__.py
index d84ff65..7235fd6 100644
--- a/libapol/__init__.py
+++ b/libapol/__init__.py
@@ -39,6 +39,9 @@ import terulequery
import rbacrulequery
import mlsrulequery
+# In-policy Context Queries
+import initsidquery
+
# Information Flow Analysis
import infoflow
import permmap
diff --git a/libapol/contextquery.py b/libapol/contextquery.py
new file mode 100644
index 0000000..237af30
--- /dev/null
+++ b/libapol/contextquery.py
@@ -0,0 +1,167 @@
+# Copyright 2014, Tresys Technology, LLC
+#
+# This file is part of SETools.
+#
+# SETools is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation, either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# SETools 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with SETools. If not, see
+# .
+#
+import re
+
+import query
+
+
+class ContextQuery(query.PolicyQuery):
+
+ """Abstract base class for SETools in-policy labeling/context queries."""
+
+ @staticmethod
+ def _match_context(context,
+ user, user_regex, user_recomp,
+ role, role_regex, role_recomp,
+ type_, type_regex, type_recomp,
+ range_):
+ """
+ Match the context with optional regular expression.
+
+ Parameters:
+ context The object to match.
+ user The user to match in the context.
+ user_regex If true, regular expression matching
+ will be used on the user.
+ user_recomp The compiled user regular expression.
+ role The role to match in the context.
+ role_regex If true, regular expression matching
+ will be used on the role.
+ role_recomp The compiled role regular expression.
+ type_ The type to match in the context.
+ type_regex If true, regular expression matching
+ will be used on the type.
+ type_recomp The compiled type regular expression.
+ range_ The range to match in the context.
+ """
+
+ if user and not query.PolicyQuery._match_regex(
+ context.user,
+ user,
+ user_regex,
+ user_recomp):
+ return False
+
+ if role and not query.PolicyQuery._match_regex(
+ context.role,
+ role,
+ role_regex,
+ role_recomp):
+ return False
+
+ if type_ and not query.PolicyQuery._match_regex(
+ context.type_,
+ type_,
+ type_regex,
+ type_recomp):
+ return False
+
+ if range_:
+ raise NotImplementedError(
+ "Context range queries are not yet implemented.")
+
+ return True
+
+ def set_user(self, user, **opts):
+ """
+ Set the criteria for matching the context's user.
+
+ Parameter:
+ user Name to match the context's user.
+ regex If true, regular expression matching will be used.
+
+ Exceptions:
+ NameError Invalid keyword option.
+ """
+
+ self.user = str(user)
+
+ for k in opts.keys():
+ if k == "regex":
+ self.user_regex = opts[k]
+ else:
+ raise NameError("Invalid name option: {0}".format(k))
+
+ if self.user_regex:
+ self.user_cmp = re.compile(self.name)
+ else:
+ self.user_cmp = None
+
+ def set_role(self, role, **opts):
+ """
+ Set the criteria for matching the context's role.
+
+ Parameter:
+ role Name to match the context's role.
+ regex If true, regular expression matching will be used.
+
+ Exceptions:
+ NameError Invalid keyword option.
+ """
+
+ self.role = str(role)
+
+ for k in opts.keys():
+ if k == "regex":
+ self.role_regex = opts[k]
+ else:
+ raise NameError("Invalid name option: {0}".format(k))
+
+ if self.role_regex:
+ self.role_cmp = re.compile(self.name)
+ else:
+ self.role_cmp = None
+
+ def set_type(self, type_, **opts):
+ """
+ Set the criteria for matching the context's type.
+
+ Parameter:
+ type_ Name to match the context's type.
+ regex If true, regular expression matching will be used.
+
+ Exceptions:
+ NameError Invalid keyword option.
+ """
+
+ self.type_ = str(type_)
+
+ for k in opts.keys():
+ if k == "regex":
+ self.type_regex = opts[k]
+ else:
+ raise NameError("Invalid name option: {0}".format(k))
+
+ if self.type_regex:
+ self.type_cmp = re.compile(self.name)
+ else:
+ self.type_cmp = None
+
+ def set_range(self, range_, **opts):
+ """
+ Set the criteria for matching the context's range.
+
+ Parameter:
+ range_ Range to match the context's range.
+
+ Exceptions:
+ NameError Invalid keyword option.
+ """
+
+ self.range_ = range_
diff --git a/libapol/initsidquery.py b/libapol/initsidquery.py
new file mode 100644
index 0000000..4b9ddf8
--- /dev/null
+++ b/libapol/initsidquery.py
@@ -0,0 +1,82 @@
+# Copyright 2014, Tresys Technology, LLC
+#
+# This file is part of SETools.
+#
+# SETools is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation, either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# SETools 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with SETools. If not, see
+# .
+#
+import compquery
+import contextquery
+
+
+class InitialSIDQuery(compquery.ComponentQuery, contextquery.ContextQuery):
+
+ """Initial SID (context) query."""
+
+ def __init__(self, policy,
+ name="", name_regex=False,
+ user="", user_regex=False,
+ role="", role_regex=False,
+ type_="", type_regex=False,
+ range_=""):
+ """
+ Parameters:
+ policy The policy to query.
+
+ user The criteria to match the context's user.
+ user_regex If true, regular expression matching
+ will be used on the user.
+ role The criteria to match the context's role.
+ role_regex If true, regular expression matching
+ will be used on the role.
+ type_ The criteria to match the context's type.
+ type_regex If true, regular expression matching
+ will be used on the type.
+ range_ The criteria to match the context's range.
+ """
+
+ self.policy = policy
+
+ self.set_name(name, regex=name_regex)
+ self.set_user(user, regex=user_regex)
+ self.set_role(role, regex=role_regex)
+ self.set_type(type_, regex=type_regex)
+ self.set_range(range_)
+
+ def results(self):
+ """Generator which yields all matching initial SIDs."""
+
+ for i in self.policy.initialsids():
+ if self.name and not self._match_regex(
+ i,
+ self.name,
+ self.name_regex,
+ self.name_cmp):
+ continue
+
+ if not self._match_context(
+ i.context,
+ self.user,
+ self.user_regex,
+ self.user_cmp,
+ self.role,
+ self.role_regex,
+ self.role_cmp,
+ self.type_,
+ self.type_regex,
+ self.type_cmp,
+ self.range_):
+ continue
+
+ yield i
diff --git a/seinfo b/seinfo
index b61dd85..d680223 100755
--- a/seinfo
+++ b/seinfo
@@ -144,3 +144,15 @@ if args.classquery:
print(c.statement())
else:
print(c)
+
+if args.initialsidquery:
+ if isinstance(args.initialsidquery, str):
+ q = libapol.initsidquery.InitialSIDQuery(p, args.initialsidquery)
+ else:
+ q = libapol.initsidquery.InitialSIDQuery(p)
+
+ for i in sorted(q.results()):
+ if args.expand:
+ print(i.statement())
+ else:
+ print(i)