diff options
Diffstat (limited to 'lib/python2.7/site-packages/sepolgen/module.py')
-rw-r--r-- | lib/python2.7/site-packages/sepolgen/module.py | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/lib/python2.7/site-packages/sepolgen/module.py b/lib/python2.7/site-packages/sepolgen/module.py new file mode 100644 index 0000000..c09676a --- /dev/null +++ b/lib/python2.7/site-packages/sepolgen/module.py @@ -0,0 +1,216 @@ +# 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 +# + +""" +Utilities for dealing with the compilation of modules and creation +of module tress. +""" + +import re +import tempfile +try: + from subprocess import getstatusoutput +except ImportError: + from commands import getstatusoutput +import os +import os.path +import shutil + +import selinux + +from . import defaults + + +def is_valid_name(modname): + """Check that a module name is valid. + """ + m = re.findall("[^a-zA-Z0-9_\-\.]", modname) + if len(m) == 0 and modname[0].isalpha(): + return True + else: + return False + +class ModuleTree: + def __init__(self, modname): + self.modname = modname + self.dirname = None + + def dir_name(self): + return self.dirname + + def te_name(self): + return self.dirname + "/" + self.modname + ".te" + + def fc_name(self): + return self.dirname + "/" + self.modname + ".fc" + + def if_name(self): + return self.dirname + "/" + self.modname + ".if" + + def package_name(self): + return self.dirname + "/" + self.modname + ".pp" + + def makefile_name(self): + return self.dirname + "/Makefile" + + def create(self, parent_dirname, makefile_include=None): + self.dirname = parent_dirname + "/" + self.modname + os.mkdir(self.dirname) + fd = open(self.makefile_name(), "w") + if makefile_include: + fd.write("include " + makefile_include) + else: + fd.write("include " + defaults.refpolicy_makefile()) + fd.close() + + # Create empty files for the standard refpolicy + # module files + open(self.te_name(), "w").close() + open(self.fc_name(), "w").close() + open(self.if_name(), "w").close() + +def modname_from_sourcename(sourcename): + return os.path.splitext(os.path.split(sourcename)[1])[0] + +class ModuleCompiler: + """ModuleCompiler eases running of the module compiler. + + The ModuleCompiler class encapsulates running the commandline + module compiler (checkmodule) and module packager (semodule_package). + You are likely interested in the create_module_package method. + + Several options are controlled via paramaters (only effects the + non-refpol builds): + + .mls [boolean] Generate an MLS module (by passed -M to + checkmodule). True to generate an MLS module, false + otherwise. + + .module [boolean] Generate a module instead of a base module. + True to generate a module, false to generate a base. + + .checkmodule [string] Fully qualified path to the module compiler. + Default is /usr/bin/checkmodule. + + .semodule_package [string] Fully qualified path to the module + packager. Defaults to /usr/bin/semodule_package. + .output [file object] File object used to write verbose + output of the compililation and packaging process. + """ + def __init__(self, output=None): + """Create a ModuleCompiler instance, optionally with an + output file object for verbose output of the compilation process. + """ + self.mls = selinux.is_selinux_mls_enabled() + self.module = True + self.checkmodule = "/usr/bin/checkmodule" + self.semodule_package = "/usr/bin/semodule_package" + self.output = output + self.last_output = "" + self.refpol_makefile = defaults.refpolicy_makefile() + self.make = "/usr/bin/make" + + def o(self, str): + if self.output: + self.output.write(str + "\n") + self.last_output = str + + def run(self, command): + self.o(command) + rc, output = getstatusoutput(command) + self.o(output) + + return rc + + def gen_filenames(self, sourcename): + """Generate the module and policy package filenames from + a source file name. The source file must be in the form + of "foo.te". This will generate "foo.mod" and "foo.pp". + + Returns a tuple with (modname, policypackage). + """ + splitname = sourcename.split(".") + if len(splitname) < 2: + raise RuntimeError("invalid sourcefile name %s (must end in .te)", sourcename) + # Handle other periods in the filename correctly + basename = ".".join(splitname[0:-1]) + modname = basename + ".mod" + packagename = basename + ".pp" + + return (modname, packagename) + + def create_module_package(self, sourcename, refpolicy=True): + """Create a module package saved in a packagename from a + sourcename. + + The create_module_package creates a module package saved in a + file named sourcename (.pp is the standard extension) from a + source file (.te is the standard extension). The source file + should contain SELinux policy statements appropriate for a + base or non-base module (depending on the setting of .module). + + Only file names are accepted, not open file objects or + descriptors because the command line SELinux tools are used. + + On error a RuntimeError will be raised with a descriptive + error message. + """ + if refpolicy: + self.refpol_build(sourcename) + else: + modname, packagename = self.gen_filenames(sourcename) + self.compile(sourcename, modname) + self.package(modname, packagename) + os.unlink(modname) + + def refpol_build(self, sourcename): + # Compile + command = self.make + " -f " + self.refpol_makefile + rc = self.run(command) + + # Raise an error if the process failed + if rc != 0: + raise RuntimeError("compilation failed:\n%s" % self.last_output) + + def compile(self, sourcename, modname): + s = [self.checkmodule] + if self.mls: + s.append("-M") + if self.module: + s.append("-m") + s.append("-o") + s.append(modname) + s.append(sourcename) + + rc = self.run(" ".join(s)) + if rc != 0: + raise RuntimeError("compilation failed:\n%s" % self.last_output) + + def package(self, modname, packagename): + s = [self.semodule_package] + s.append("-o") + s.append(packagename) + s.append("-m") + s.append(modname) + + rc = self.run(" ".join(s)) + if rc != 0: + raise RuntimeError("packaging failed [%s]" % self.last_output) + + |