|
From: <ssm...@us...> - 2007-02-05 19:01:33
|
Revision: 2220
http://svn.sourceforge.net/selinux/?rev=2220&view=rev
Author: ssmalley
Date: 2007-02-05 11:01:07 -0800 (Mon, 05 Feb 2007)
Log Message:
-----------
Author: Karl MacMillan
Email: kma...@me...
Subject: add sepolgen
Date: Wed, 31 Jan 2007 11:43:14 -0500
The patch at [1] adds the sepolgen python library for policy generation
and a new implementation of audit2allow based on this library. The
library has facilities for:
* parsing audit messages
* parsing and representing policy (including refpolicy interfaces)
* manipulating / transforming policy (e.g., adding require statements)
* generating policy from access requests / audit messages (including
calls to refpolicy interfaces)
* outputting policy as text
* compiling policy modules
All of the requested updates from the previous review have been made.
Notes for packaging:
* This adds a new dependency between policycoreutils and sepolgen
* The tool sepolgen-ifgen needs to be run to extract information from
the reference policy headers for audit2allow to generate refpolicy. The
rpm spec file at
http://hg.et.redhat.com/selinux/madison?f=b26375c7641a;file=madison.spec
shows how I did this.
* Audit2allow currently has a few regressions from the old version. This
will be fixed soon.
[1]
http://people.redhat.com/kmacmill/patches/selinux/sepolgen-initial-submission.patch.gz
Signed-off-by: Karl MacMillan <kma...@me...>
Modified Paths:
--------------
trunk/Makefile
trunk/policycoreutils/ChangeLog
trunk/policycoreutils/VERSION
trunk/policycoreutils/audit2allow/Makefile
trunk/policycoreutils/audit2allow/audit2allow
Added Paths:
-----------
trunk/policycoreutils/audit2allow/sepolgen-ifgen
trunk/sepolgen/
trunk/sepolgen/COPYING
trunk/sepolgen/HACKING
trunk/sepolgen/Makefile
trunk/sepolgen/VERSION
trunk/sepolgen/src/
trunk/sepolgen/src/Makefile
trunk/sepolgen/src/sepolgen/
trunk/sepolgen/src/sepolgen/Makefile
trunk/sepolgen/src/sepolgen/__init__.py
trunk/sepolgen/src/sepolgen/access.py
trunk/sepolgen/src/sepolgen/audit.py
trunk/sepolgen/src/sepolgen/classperms.py
trunk/sepolgen/src/sepolgen/defaults.py
trunk/sepolgen/src/sepolgen/interfaces.py
trunk/sepolgen/src/sepolgen/lex.py
trunk/sepolgen/src/sepolgen/matching.py
trunk/sepolgen/src/sepolgen/module.py
trunk/sepolgen/src/sepolgen/objectmodel.py
trunk/sepolgen/src/sepolgen/output.py
trunk/sepolgen/src/sepolgen/policygen.py
trunk/sepolgen/src/sepolgen/refparser.py
trunk/sepolgen/src/sepolgen/refpolicy.py
trunk/sepolgen/src/sepolgen/sepolgeni18n.py
trunk/sepolgen/src/sepolgen/util.py
trunk/sepolgen/src/sepolgen/yacc.py
trunk/sepolgen/src/share/
trunk/sepolgen/src/share/Makefile
trunk/sepolgen/src/share/perm_map
trunk/sepolgen/tests/
trunk/sepolgen/tests/Makefile
trunk/sepolgen/tests/audit.txt
trunk/sepolgen/tests/module_compile_test.te
trunk/sepolgen/tests/perm_map
trunk/sepolgen/tests/run-tests.py
trunk/sepolgen/tests/test_access.py
trunk/sepolgen/tests/test_audit.py
trunk/sepolgen/tests/test_data/
trunk/sepolgen/tests/test_data/audit.log
trunk/sepolgen/tests/test_data/httpd.log
trunk/sepolgen/tests/test_data/short.log
trunk/sepolgen/tests/test_interfaces.py
trunk/sepolgen/tests/test_matching.py
trunk/sepolgen/tests/test_module.py
trunk/sepolgen/tests/test_objectmodel.py
trunk/sepolgen/tests/test_policygen.py
trunk/sepolgen/tests/test_refparser.py
trunk/sepolgen/tests/test_refpolicy.py
Removed Paths:
-------------
trunk/policycoreutils/audit2allow/avc.py
Modified: trunk/Makefile
===================================================================
--- trunk/Makefile 2007-02-05 18:01:59 UTC (rev 2219)
+++ trunk/Makefile 2007-02-05 19:01:07 UTC (rev 2220)
@@ -1,4 +1,4 @@
-SUBDIRS=libsepol libselinux libsemanage checkpolicy policycoreutils # policy
+SUBDIRS=libsepol libselinux libsemanage sepolgen checkpolicy policycoreutils # policy
PYSUBDIRS=libselinux libsemanage
ifeq ($(DEBUG),1)
Modified: trunk/policycoreutils/ChangeLog
===================================================================
--- trunk/policycoreutils/ChangeLog 2007-02-05 18:01:59 UTC (rev 2219)
+++ trunk/policycoreutils/ChangeLog 2007-02-05 19:01:07 UTC (rev 2220)
@@ -1,3 +1,9 @@
+2.0.0 2007-02-05
+ * Merged new audit2allow from Karl MacMillan.
+ This audit2allow depends on the new sepolgen python module.
+ Note that you must run the sepolgen-ifgen tool to generate
+ the data needed by audit2allow to generate refpolicy.
+
1.34.1 2007-01-22
* Fixed newrole non-pam build.
Modified: trunk/policycoreutils/VERSION
===================================================================
--- trunk/policycoreutils/VERSION 2007-02-05 18:01:59 UTC (rev 2219)
+++ trunk/policycoreutils/VERSION 2007-02-05 19:01:07 UTC (rev 2220)
@@ -1 +1 @@
-1.34.1
+2.0.0
Modified: trunk/policycoreutils/audit2allow/Makefile
===================================================================
--- trunk/policycoreutils/audit2allow/Makefile 2007-02-05 18:01:59 UTC (rev 2219)
+++ trunk/policycoreutils/audit2allow/Makefile 2007-02-05 19:01:07 UTC (rev 2220)
@@ -4,23 +4,19 @@
LIBDIR ?= $(PREFIX)/lib
MANDIR ?= $(PREFIX)/share/man
LOCALEDIR ?= /usr/share/locale
-PYLIBVER ?= $(shell python -c 'import sys;print "python%d.%d" % sys.version_info[0:2]')
-PYTHONLIBDIR ?= $(LIBDIR)/$(PYLIBVER)
-TARGETS=audit2allow
+all: ;
-all: $(TARGETS)
-
install: all
-mkdir -p $(BINDIR)
- install -m 755 $(TARGETS) $(BINDIR)
+ install -m 755 audit2allow $(BINDIR)
+ install -m 755 sepolgen-ifgen $(BINDIR)
-mkdir -p $(MANDIR)/man1
install -m 644 audit2allow.1 $(MANDIR)/man1/
- test -d $(PYTHONLIBDIR)/site-packages || install -m 755 -d $(PYTHONLIBDIR)/site-packages
- install -m 755 avc.py $(PYTHONLIBDIR)/site-packages
clean:
+ rm -f *~
-indent:
+indent: ;
-relabel:
+relabel: ;
Modified: trunk/policycoreutils/audit2allow/audit2allow
===================================================================
--- trunk/policycoreutils/audit2allow/audit2allow 2007-02-05 18:01:59 UTC (rev 2219)
+++ trunk/policycoreutils/audit2allow/audit2allow 2007-02-05 19:01:07 UTC (rev 2220)
@@ -1,226 +1,268 @@
#! /usr/bin/python -E
-# Copyright (C) 2005 Red Hat
+# Authors: Karl MacMillan <kma...@me...>
+#
+# Copyright (C) 2006 Red Hat
# see file 'COPYING' for use and warranty information
#
-# Audit2allow is a rewrite of prior perl script.
+# 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
#
-# Based off original audit2allow perl script: which credits
-# newrules.pl, Copyright (C) 2001 Justin R. Smith (js...@mc...)
-# 2003 Oct 11: Add -l option by Yuichi Nakamura(yn...@us...)
+# 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.
#
-# 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; either version 2 of
-# the License, or (at your option) any later version.
+# 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
#
-# 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
-#
-#
-from avc import *
-if __name__ == '__main__':
- import commands, sys, os, getopt, selinux
- import gettext
- import re
+import sys
+import tempfile
+
+import sepolgen.audit as audit
+import sepolgen.policygen as policygen
+import sepolgen.interfaces as interfaces
+import sepolgen.output as output
+import sepolgen.objectmodel as objectmodel
+import sepolgen.defaults as defaults
+import sepolgen.module as module
+from sepolgen.sepolgeni18n import _
+
+class AuditToPolicy:
+ VERSION = "%prog .1"
+ SYSLOG = "/var/log/messages"
+
+ def __init__(self):
+ self.__options = None
+ self.__parser = None
+ self.__avs = None
+
+ def __parse_options(self):
+ from optparse import OptionParser
+
+ parser = OptionParser(version=self.VERSION)
+ parser.add_option("-a", "--audit", action="store_true", dest="audit", default=False,
+ help="read input from audit log - conflicts with -i")
+ parser.add_option("-d", "--dmesg", action="store_true", dest="dmesg", default=False,
+ help="read input from dmesg - conflicts with --audit and --input")
+ parser.add_option("-i", "--input", dest="input",
+ help="read input from <input> - conflicts with -a")
+ parser.add_option("-l", "--lastreload", action="store_true", dest="lastreload", default=False,
+ help="read input only after the last reload")
+ parser.add_option("-r", "--requires", action="store_true", dest="requires", default=False,
+ help="generate require statements for rules")
+ parser.add_option("-m", "--module", dest="module",
+ help="set the module name - implies --requires")
+ parser.add_option("-M", "--module-package", dest="module_package",
+ help="generate a module package - conflicts with -o and -m")
+ parser.add_option("-o", "--output", dest="output",
+ help="append output to <filename>, conflicts with -M")
+ parser.add_option("-R", "--reference", action="store_true", dest="refpolicy",
+ default=False, help="generate refpolicy style output")
+ parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
+ default=False, help="explain generated output")
+ parser.add_option("-e", "--explain", action="store_true", dest="explain_long",
+ default=False, help="fully explain generated output")
+ parser.add_option("-t", "--type", help="only process messages with a type that matches this regex",
+ dest="type")
+ parser.add_option("--perm-map", dest="perm_map", help="file name of perm map")
+ parser.add_option("--interface-info", dest="interface_info", help="file name of interface information")
+ parser.add_option("--debug", dest="debug", action="store_true", default=False,
+ help="leave generated modules for -M")
+
+ options, args = parser.parse_args()
+
+ # Make -d, -a, and -i conflict
+ if options.audit is True:
+ if options.input is not None:
+ sys.stderr.write("error: --audit conflicts with --input\n")
+ if options.dmesg is True:
+ sys.stderr.write("error: --audit conflicts with --dmesg\n")
+ if options.input is not None and options.dmesg is True:
+ sys.stderr.write("error: --input conflicts with --dmesg\n")
+
+ # Turn on requires generation if a module name is given. Also verify
+ # the module name.
+ if options.module:
+ name = options.module
+ else:
+ name = options.module_package
+ if name:
+ options.requires = True
+ if not module.is_valid_name(name):
+ sys.stderr.write("only letters and numbers allowed in module names\n")
+ sys.exit(2)
+
+
+ # Make -M and -o conflict
+ if options.module_package:
+ if options.output:
+ sys.stderr.write("error: --module-package conflicts with --output\n")
+ sys.exit(2)
+ if options.module:
+ sys.stderr.write("error: --module-package conflicts with --module\n")
+ sys.exit(2)
+
+ self.__options = options
+
+ def __read_input(self):
+ parser = audit.AuditParser(last_load_only=self.__options.lastreload)
+
+ filename = None
+ messages = None
+ f = None
+
+ # Figure out what input we want
+ if self.__options.input is not None:
+ filename = self.__options.input
+ elif self.__options.dmesg:
+ messages = audit.get_dmesg_msgs()
+ elif self.__options.audit:
+ try:
+ messages = audit.get_audit_msgs()
+ except OSError, e:
+ sys.stderr.write('could not run ausearch - "%s"\n' % str(e))
+ sys.exit(1)
+ else:
+ # This is the default if no input is specified
+ f = sys.stdin
+
+ # Get the input
+ if filename is not None:
+ try:
+ f = open(filename)
+ except IOError, e:
+ sys.stderr.write('could not open file %s - "%s"\n' % (filename, str(e)))
+ sys.exit(1)
+
+ if f is not None:
+ parser.parse_file(f)
+ f.close()
+
+ if messages is not None:
+ parser.parse_string(messages)
+
+ self.__parser = parser
+
+ def __process_input(self):
+ if self.__options.type:
+ filter = audit.TypeFilter(self.__options.type)
+ self.__avs = self.__parser.to_access(filter)
+ else:
+ self.__avs = self.__parser.to_access()
+
+ def __load_interface_info(self):
+ # Load interface info file
+ if self.__options.interface_info:
+ fn = self.__options.interface_info
+ else:
+ fn = defaults.interface_info()
try:
- gettext.install('policycoreutils')
+ fd = open(fn)
except:
- pass
- def get_mls_flag():
- if selinux.is_selinux_mls_enabled():
- return "-M"
- else:
- return ""
+ sys.stderr.write("could not open interface info [%s]\n" % fn)
+ sys.exit(1)
- def usage(msg = ""):
- print _('audit2allow [-adhilrv] [-t file ] [ -f fcfile ] [-i <inputfile> ] [[-m|-M] <modulename> ] [-o <outputfile>]\n\
- -a, --all read input from audit and message log, conflicts with -i\n\
- -d, --dmesg read input from output of /bin/dmesg\n\
- -h, --help display this message\n\
- -i, --input read input from <inputfile> conflicts with -a\n\
- -l, --lastreload read input only after last \"load_policy\"\n\
- -m, --module generate module/require output <modulename> \n\
- -M generate loadable module package, conflicts with -o\n\
- -o, --output append output to <outputfile>, conflicts with -M\n\
- -r, --requires generate require output \n\
- -t, --tefile Add input from Existing Type Enforcement file\n\
- -f, --fcfile Existing Type Enforcement file, requires -M\n\
- -v, --verbose verbose output\n\
- -A, --analyze Analyze output\n\
- ')
- if msg != "":
- print msg
- sys.exit(1)
-
- def verify_module(module):
- m = re.findall("[^a-zA-Z0-9]", module)
- if len(m) != 0:
- usage(_("Alphanumeric Charaters Only"))
-
- def errorExit(error):
- sys.stderr.write("%s: " % sys.argv[0])
- sys.stderr.write("%s\n" % error)
- sys.stderr.flush()
- sys.exit(1)
+ ifs = interfaces.InterfaceSet()
+ ifs.from_file(fd)
+ fd.close()
- #
- #
- #
- try:
- last_reload = 0
- inputfd = sys.stdin
- output = sys.stdout
- module = ""
- requires = 0
- verbose = 0
- auditlogs = 0
- buildPP = 0
- input_ind = 0
- output_ind = 0
- ref_ind = False
- analyze = False
- te_inputs = []
+ # Also load perm maps
+ if self.__options.perm_map:
+ fn = self.__options.perm_map
+ else:
+ fn = defaults.perm_map()
+ try:
+ fd = open(fn)
+ except:
+ sys.stderr.write("could not open perm map [%s]\n" % fn)
+ sys.exit(1)
- fc_file = ""
- gopts, cmds = getopt.getopt(sys.argv[1:],
- 'Aadf:hi:lm:M:o:rt:vR',
- ['all',
- 'analyze',
- 'dmesg',
- 'fcfile=',
- 'help',
- 'input=',
- 'lastreload',
- 'module=',
- 'output=',
- 'requires',
- 'reference',
- 'tefile=',
- 'verbose'
- ])
- for o,a in gopts:
- if o == "-a" or o == "--all":
- if input_ind:
- usage()
- inputfd = open("/var/log/messages", "r")
- auditlogs = 1
- if o == "-d" or o == "--dmesg":
- inputfd = os.popen("/bin/dmesg", "r")
- if o == "-f" or o == "--fcfile":
- if a[0] == "-":
- usage()
- fc_file = a
- if o == "-h" or o == "--help":
- usage()
- if o == "-i"or o == "--input":
- if auditlogs or a[0] == "-":
- usage()
- input_ind = 1
- inputfd = open(a, "r")
- if o == '--lastreload' or o == "-l":
- last_reload = 1
- if o == "-m" or o == "--module":
- if module != "" or a[0] == "-":
- usage()
- module = a
- verify_module(module)
- if o == "-M":
- if module != "" or output_ind or a[0] == "-":
- usage()
- module = a
- verify_module(module)
- outfile = a+".te"
- buildPP = 1
- if not os.path.exists("/usr/bin/checkmodule"):
- errorExit("-M Requires the checkmodule command, you need to install the checkpolicy rpm package")
- output = open(outfile, "w")
- if o == "-r" or o == "--requires":
- requires = 1
- if o == "-t" or o == "--tefile":
- te_inputs.append(open(a, "r"))
-
- if o == "-R" or o == "--reference":
- ref_ind = True
-
- if o == "-o" or o == "--output":
- if module != "" or a[0] == "-":
- usage()
- output = open(a, "a")
- output_ind = 1
- if o == "-v" or o == "--verbose":
- verbose = 1
-
- if o == "-A" or o == "--analyze":
- analyze = True
-
- if len(cmds) != 0:
- usage()
+ perm_maps = objectmodel.PermMappings()
+ perm_maps.from_file(fd)
+
+ return (ifs, perm_maps)
+
+
+ def __output(self):
+ g = policygen.PolicyGenerator()
+
+ if self.__options.module:
+ g.set_module_name(self.__options.module)
+
+ # Interface generation
+ if self.__options.refpolicy:
+ ifs, perm_maps = self.__load_interface_info()
+ g.set_gen_refpol(ifs, perm_maps)
- if fc_file != "" and not buildPP:
- usage("Error %s: Option -fc requires -M" % sys.argv[0])
-
- serules = SERules(last_reload, verbose)
+ # Explanation
+ if self.__options.verbose:
+ g.set_gen_explain(policygen.SHORT_EXPLANATION)
+ if self.__options.explain_long:
+ g.set_gen_explain(policygen.LONG_EXPLANATION)
- for i in te_inputs:
- te = TERules(serules)
- te.load(i)
+ # Requires
+ if self.__options.requires:
+ g.set_gen_requires(True)
- serules.load(inputfd)
+ # Generate the policy
+ g.add_access(self.__avs)
+ # Output
+ writer = output.ModuleWriter()
- if ref_ind:
- serules.gen_reference_policy()
+ # Module package
+ if self.__options.module_package:
+ g.set_module_name(self.__options.module_package)
- if analyze:
- serules.analyze()
- sys.exit(0)
+ fd = tempfile.NamedTemporaryFile()
+ writer.write(g.get_module(), fd)
+ fd.flush()
+
+ mc = module.ModuleCompiler()
+ if self.__options.debug:
+ clean = False
+ else:
+ clean = True
- if auditlogs and os.path.exists("/var/log/audit/audit.log"):
- inputfd = os.popen("ausearch -m avc,MAC_POLICY_LOAD")
- serules.load(inputfd)
+ if self.__options.refpolicy:
+ mc.refpolicy = True
+
+ try:
+ mc.create_module_package(fd.name, self.__options.module_package + ".pp",
+ cleanup=clean)
+ except RuntimeError, e:
+ print e
+ sys.exit(1)
- if buildPP:
- print (_("Generating type enforcment file: %s.te") % module)
- output.write(serules.out(requires, module))
- output.flush()
- if buildPP:
- if ref_ind:
- rc, type = selinux.selinux_getpolicytype()
- cmd = "make -f /usr/share/selinux/%s/include/Makefile %s.pp" % (type, module)
- print _("Compiling policy")
- print cmd
- rc = commands.getstatusoutput(cmd)
- else:
- cmd = "checkmodule %s -m -o %s.mod %s.te" % (get_mls_flag(), module, module)
- print _("Compiling policy")
- print cmd
- rc = commands.getstatusoutput(cmd)
- if rc[0] == 0:
- cmd = "semodule_package -o %s.pp -m %s.mod" % (module, module)
- if fc_file != "":
- cmd = "%s -f %s" % (cmd, fc_file)
-
- print cmd
- rc = commands.getstatusoutput(cmd)
- if rc[0] == 0:
- print _("\n******************** IMPORTANT ***********************\n")
- print (_("In order to load this newly created policy package into the kernel,\nyou are required to execute \n\nsemodule -i %s.pp\n\n") % module)
- else:
- errorExit(rc[1])
+ # This should unlink the temporary file
+ fd.close()
+ sys.stdout.write(_("******************** IMPORTANT ***********************\n"))
+ sys.stdout.write((_("To make this policy package active, execute:" +\
+ "\n\nsemodule -i %s.pp\n\n") % self.__options.module_package))
+
+ else:
+ # File or stdout
+ if self.__options.module:
+ g.set_module_name(self.__options.module)
- except getopt.error, error:
- errorExit(_("Options Error: %s ") % error.msg)
- except ValueError, error:
- errorExit(error.args[0])
- except IOError, error:
- errorExit(error)
- except KeyboardInterrupt, error:
- sys.exit(0)
+ if self.__options.output:
+ fd = open(self.__options.output, "w")
+ else:
+ fd = sys.stdout
+ writer.write(g.get_module(), fd)
+
+ def main(self):
+ try:
+ self.__parse_options()
+ self.__read_input()
+ self.__process_input()
+ self.__output()
+ except KeyboardInterrupt:
+ sys.exit(0)
+
+if __name__ == "__main__":
+ app = AuditToPolicy()
+ app.main()
Deleted: trunk/policycoreutils/audit2allow/avc.py
===================================================================
--- trunk/policycoreutils/audit2allow/avc.py 2007-02-05 18:01:59 UTC (rev 2219)
+++ trunk/policycoreutils/audit2allow/avc.py 2007-02-05 19:01:07 UTC (rev 2220)
@@ -1,553 +0,0 @@
-#! /usr/bin/python -E
-# Copyright (C) 2006 Red Hat
-# see file 'COPYING' for use and warranty information
-#
-# avc.py is a plugin modules used by audit2allow and other objects to process
-# avc messages from the log files
-#
-# Based off original audit2allow perl script: which credits
-# newrules.pl, Copyright (C) 2001 Justin R. Smith (js...@mc...)
-# 2003 Oct 11: Add -l option by Yuichi Nakamura(yn...@us...)
-#
-# 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; either version 2 of
-# the License, or (at your option) any later version.
-#
-# 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
-#
-#
-import sys, os, pwd, string, re, selinux
-
-obj = "(\{[^\}]*\}|[^ \t:]*)"
-allow_regexp = "(allow|dontaudit)[ \t]+%s[ \t]*%s[ \t]*:[ \t]*%s[ \t]*%s" % (obj, obj, obj, obj)
-awk_script = '/^[[:blank:]]*interface[[:blank:]]*\(/ {\n\
- IFACEFILE=FILENAME\n\
- IFACENAME = gensub("^[[:blank:]]*interface[[:blank:]]*\\\\(\`?","","g",$0);\n\
- IFACENAME = gensub("\'?,.*$","","g",IFACENAME);\n\
-}\n\
-\n\
-/^[[:blank:]]*(allow|dontaudit)[[:blank:]]+.*;[[:blank:]]*$/ {\n\
-\n\
- if ((length(IFACENAME) > 0) && (IFACEFILE == FILENAME)){\n\
- ALLOW = gensub("^[[:blank:]]*","","g",$0)\n\
- ALLOW = gensub(";[[:blank:]]*$","","g",$0)\n\
- print FILENAME "\\t" IFACENAME "\\t" ALLOW;\n\
- }\n\
-}\
-'
-
-class context:
- def __init__(self, scontext):
- self.scontext = scontext
- con=scontext.split(":")
- self.user = con[0]
- self.role = con[1]
- self.type = con[2]
- if len(con) > 3:
- self.mls = con[3]
- else:
- self.mls = "s0"
-
- def __str__(self):
- return self.scontext
-
-class accessTrans:
- def __init__(self):
- self.dict = {}
- try:
- fd = open("/usr/share/selinux/devel/include/support/obj_perm_sets.spt")
- except IOError, error:
- raise IOError("Reference policy generation requires the policy development package selinux-policy-devel.\n%s" % error)
- records = fd.read().split("\n")
- regexp = "^define *\(`([^']*)' *, *` *\{([^}]*)}'"
- for r in records:
- m = re.match(regexp,r)
- if m != None:
- self.dict[m.groups()[0]] = m.groups()[1].split()
- fd.close()
- def get(self, var):
- l = []
- for v in var:
- if v in self.dict.keys():
- l += self.dict[v]
- else:
- if v not in ("{", "}"):
- l.append(v)
- return l
-
-class interfaces:
- def __init__(self):
- self.dict = {}
- trans = accessTrans()
- (input, output) = os.popen2("awk -f - /usr/share/selinux/devel/include/*/*.if 2> /dev/null")
- input.write(awk_script)
- input.close()
- records = output.read().split("\n")
- input.close()
- if len(records) > 0:
- regexp = "([^ \t]*)[ \t]+([^ \t]*)[ \t]+%s" % allow_regexp
- for r in records:
- m = re.match(regexp,r)
- if m == None:
- continue
- val = m.groups()
- file = os.path.basename(val[0]).split(".")[0]
- iface = val[1]
- Scon = val[3].split()
- Tcon = val[4].split()
- Class = val[5].split()
- Access = trans.get(val[6].split())
- for s in Scon:
- for t in Tcon:
- for c in Class:
- if (s, t, c) not in self.dict.keys():
- self.dict[(s, t, c)] = []
- self.dict[(s, t, c)].append((Access, file, iface))
- def out(self):
- keys = self.dict.keys()
- keys.sort()
- for k in keys:
- print k
- for i in self.dict[k]:
- print "\t", i
-
- def match(self, Scon, Tcon, Class, Access):
- keys = self.dict.keys()
- ret = []
- if (Scon, Tcon, Class) in keys:
- for i in self.dict[(Scon, Tcon, Class)]:
- if Access in i[0]:
- if i[2].find(Access) >= 0:
- ret.insert(0, i)
- else:
- ret.append(i)
- return ret
- if ("$1", Tcon, Class) in keys:
- for i in self.dict[("$1", Tcon, Class)]:
- if Access in i[0]:
- if i[2].find(Access) >= 0:
- ret.insert(0, i)
- else:
- ret.append(i)
- return ret
- if (Scon, "$1", Class) in keys:
- for i in self.dict[(Scon, "$1", Class)]:
- if Access in i[0]:
- if i[2].find(Access) >= 0:
- ret.insert(0, i)
- else:
- ret.append(i)
- return ret
- else:
- return ret
-
-import glob, imp
-pluginPath = "/usr/share/selinux/plugins"
-if not pluginPath in sys.path:
- sys.path.append(pluginPath)
-
-class Analyze:
- def __init__(self):
- self.plugins = []
- for p in glob.glob("/usr/share/selinux/plugins/*.py"):
- plugin = os.path.basename(p)[:-3]
- self.plugins.append(imp.load_module(plugin, *imp.find_module(plugin)))
-
- def process(self, AVCS):
- ret = []
- avcs = AVCS
- for p in self.plugins:
- if avcs == None:
- break;
- r = p.analyze(avcs)
- if len(r) == 0:
- continue
- avcs = r[1]
- if len(r[0]) > 0:
- ret.append(r[0])
- return ret
-
-class serule:
- def __init__(self, key):
- self.type = key[0]
- self.source = key[1]
- self.target = key[2]
- self.seclass = key[3]
- self.access = []
- self.avcinfo = {}
- self.iface = None
-
- def add(self, avc):
- for a in avc[0]:
- if a not in self.avcinfo.keys():
- self.avcinfo[a] = []
- self.access.append(a)
- self.avcinfo[a].append(avc[1:])
-
- def getAccess(self):
- if len(self.access) == 1:
- return self.access[0]
- else:
- self.access.sort()
- return "{ " + string.join(self.access) +" }"
-
- def getName(self):
- print self.avcinfo
-
- def out(self, verbose = 0):
- ret = ""
- ret = ret+"%s %s %s:%s %s;" % (self.type, self.source, self.gettarget(), self.seclass, self.getAccess())
- if verbose:
- keys = self.avcinfo.keys()
- keys.sort()
- for i in keys:
- for x in self.avcinfo[i]:
- ret = ret+"\n\t#TYPE=AVC MSG=%s " % x[0]
- if len(x[1]):
- ret=ret+"COMM=%s " % x[1]
- if len(x[2]):
- ret=ret+"NAME=%s " % x[2]
- ret = ret + " : " + i
- return ret
-
- def gen_reference_policy(self, iface):
- ret = ""
- Scon = self.source
- Tcon = self.gettarget()
- Class = self.seclass
- Access = self.getAccess()
- m = iface.match(Scon,Tcon,Class,Access)
- if len(m) == 0:
- return self.out()
- else:
- file = m[0][1]
- ret = "\n#%s\n"% self.out()
- ret += "optional_policy(`\n"
- first = True
- for i in m:
- if file != i[1]:
- ret += "')\ngen_require(`%s', `\n" % i[1]
- file = i[1]
- first = True
- if first:
- ret += "\t%s(%s)\n" % (i[2], Scon)
- first = False
- else:
- ret += "#\t%s(%s)\n" % (i[2], Scon)
- ret += "');"
- return ret
-
- def gettarget(self):
- if self.source == self.target:
- return "self"
- else:
- return self.target
-
-def warning(error):
- sys.stderr.write("%s: " % sys.argv[0])
- sys.stderr.write("%s\n" % error)
- sys.stderr.flush()
-
-
-class TERules:
- def __init__(self, serules):
- self.VALID_CMDS = ("allow", "dontaudit", "auditallow")
- self.serules = serules
-
- def load(self, input):
- line = input.readline()
- while line:
- rec = line.split()
- if len(rec) and rec[0] in self.VALID_CMDS:
- self.add_terule(line)
- line = input.readline()
-
- def add_terule(self, rule):
- rc = rule.split(":")
- rules = rc[0].split()
- type = rules[0]
- (sources, targets) = self.rules_split(rules[1:])
- rules = rc[1].split()
- (classes, access) = self.rules_split(rules)
- for scon in sources:
- for tcon in targets:
- for seclass in classes:
- self.serules.add_rule(type, scon, tcon, seclass,access)
-
- def rules_split(self, rules):
- (idx, target ) = self.get_target(0, rules)
- (idx, subject) = self.get_target(idx, rules)
- return (target, subject)
-
- def get_target(self, i, rule):
- target = []
- if rule[i][0] == "{":
- for t in rule[i].split("{"):
- if len(t):
- target.append(t)
- i = i+1
- for s in rule[i:]:
- if s.find("}") >= 0:
- for s1 in s.split("}"):
- if len(s1):
- target.append(s1)
- i = i+1
- return (i, target)
-
- target.append(s)
- i = i+1
- else:
- if rule[i].find(";") >= 0:
- for s1 in rule[i].split(";"):
- if len(s1):
- target.append(s1)
- else:
- target.append(rule[i])
-
- i = i+1
- return (i, target)
-
-
-ALLOW = 0
-STYPE = 1
-TTYPE = 2
-CLASS = 3
-COMM = 1
-NAME = 3
-
-class SERules:
- def __init__(self, last_reload = 0, verbose = 0):
- self.last_reload = last_reload
- self.initialize()
- self.gen_ref_policy = False
- self.verbose = verbose
- self.AVCS = []
- self.INVALID_SIDS = {}
-
- def initialize(self):
- self.seRules = {}
- self.classes = {}
- self.types = []
- self.roles = []
-
- def load(self, input):
- dict = []
- found = 0
- line = input.readline()
- while line:
- rec = line.split()
- for i in rec:
- if i == "avc:" or i == "message=avc:" or i == "msg='avc:":
- found = 1
- else:
- if i == "security_compute_sid:":
- self.security_compute_sid(rec)
- found = 1
- elif i == "type=MAC_POLICY_LOAD" and self.last_reload:
- self.initialize()
- break
- else:
- dict.append(i)
-
- if not found:
- regexp = "audit\(\d+\.\d+:\d+\): policy loaded"
- m = re.match(regexp, line)
- if m !=None:
- found =1
- dict.append("load_policy")
- dict.append("granted")
-
- if found:
- self.translate(dict)
- found = 0
- dict = []
- line = input.readline()
-
-
- def translate(self,dict):
- AVC = {}
- AVC["access"] = []
- if "load_policy" in dict and self.last_reload:
- self.initialize()
-
- if "granted" in dict:
- return
- try:
- for i in range (0, len(dict)):
- if dict[i] == "{":
- i = i+1
- while i<len(dict) and dict[i] != "}":
- AVC["access"].append(dict[i])
- i = i+1
- continue
-
- t = dict[i].split('=')
- if len(t) < 2:
- continue
- AVC[t[0]] = t[1]
-
- for i in ("scontext", "tcontext", "tclass"):
- if i not in AVC.keys():
- return
- if len(AVC["access"]) == 0:
- return
-
- except IndexError, e:
- warning("Bad AVC Line: %s" % avc)
- return
-
- self.add_allow(AVC)
-
- def security_compute_sid(self, rec):
- dict={}
- for i in rec:
- t = i.split('=')
- if len(t) < 2:
- continue
- dict[t[0]]=t[1]
- try:
- r = context(dict["scontext"]).role
- t = context(dict["tcontext"]).type
- self.add_type(t)
- self.add_role(r)
- self.INVALID_SIDS[(r,t)]=rec
- except:
- return
-
- def add_avc(self, AVC):
- for a in self.AVCS:
- if a["tclass"] == AVC["tclass"] and a["access"] == AVC["access"] and a["tcontext"] == AVC["tcontext"] and a["scontext"] == AVC["scontext"] and a["comm"] == AVC["comm"] and a["name"] == AVC["name"]:
- return
- self.AVCS.append(AVC)
-
- def add_rule(self, rule_type, scon, tcon, tclass, access, msg = "", comm = "", name = ""):
- AVC = {}
- AVC["tclass"] = tclass
- AVC["access"] = access
- AVC["tcon"] = tcon
- AVC["scon"] = scon
- AVC["comm"] = comm
- AVC["name"] = name
- self.add_avc(AVC)
-
- self.add_class(tclass, access)
- self.add_type(tcon)
- self.add_type(scon)
- key = (rule_type, scon, tcon, seclass)
- if key not in self.seRules.keys():
- self.seRules[key] = serule(key)
- self.seRules[key].add((access, msg, comm, name ))
-
- def add_allow(self, AVC):
- self.add_class(AVC["tclass"], AVC["access"])
- tcontext = context(AVC["tcontext"])
- scontext = context(AVC["scontext"])
-
- self.add_type(tcontext.type)
- self.add_type(scontext.type)
-
- self.add_role(scontext.role)
-
- key = ("allow", scontext.type, tcontext.type, AVC["tclass"])
- if key not in self.seRules.keys():
- self.seRules[key] = serule(key)
-
- avckeys = AVC.keys()
- for i in ( "name", "comm", "msg" ):
- if i not in avckeys:
- AVC[i] = ""
-
- self.add_avc(AVC)
- self.seRules[key].add((AVC["access"], AVC["msg"], AVC["comm"], AVC["name"]))
-
- def add_class(self,seclass, access):
- if seclass not in self.classes.keys():
- self.classes[seclass] = []
- for a in access:
- if a not in self.classes[seclass]:
- self.classes[seclass].append(a)
-
- def add_role(self,role):
- if role not in self.roles:
- self.roles.append(role)
-
- def add_type(self,type):
- if type not in self.types:
- self.types.append(type)
-
- def gen_reference_policy(self):
- self.gen_ref_policy = True
- self.iface = interfaces()
-
- def gen_module(self, module):
- if self.gen_ref_policy:
- return "policy_module(%s, 1.0);" % module
- else:
- return "module %s 1.0;" % module
-
- def gen_requires(self):
- self.roles.sort()
- self.types.sort()
- keys = self.classes.keys()
- keys.sort()
- rec = "\n\nrequire {\n"
- if not self.gen_ref_policy:
- for i in keys:
- access = self.classes[i]
- if len(access) > 1:
- access.sort()
- rec += "\tclass %s {" % i
- for a in access:
- rec += " %s" % a
- rec += " }; \n"
- else:
- rec += "\tclass %s %s;\n" % (i, access[0])
-
- for i in self.types:
- rec += "\ttype %s; \n" % i
-
- if not self.gen_ref_policy:
- for i in self.roles:
- rec += "\trole %s; \n" % i
-
- rec += "};\n\n"
- return rec
-
- def analyze(self):
- a = Analyze()
- for i in a.process(self.AVCS):
- print i[0][0]
- print ""
-
- def out(self, require = 0, module = ""):
- rec = ""
- if len(self.seRules.keys()) == 0 and len(self.INVALID_SIDS) == 0:
- raise(ValueError("No AVC messages found."))
- if module != "":
- rec += self.gen_module(module)
- rec += self.gen_requires()
- else:
- if require:
- rec+=self.gen_requires()
-
- for i in self.INVALID_SIDS.keys():
- rec += "role %s types %s;\n" % i
-
- keys = self.seRules.keys()
- keys.sort()
- for i in keys:
- if self.gen_ref_policy:
- rec += self.seRules[i].gen_reference_policy(self.iface)+"\n"
- else:
- rec += self.seRules[i].out(self.verbose)+"\n"
- return rec
-
Added: trunk/policycoreutils/audit2allow/sepolgen-ifgen
===================================================================
--- trunk/policycoreutils/audit2allow/sepolgen-ifgen (rev 0)
+++ trunk/policycoreutils/audit2allow/sepolgen-ifgen 2007-02-05 19:01:07 UTC (rev 2220)
@@ -0,0 +1,84 @@
+#! /usr/bin/python -E
+#
+# Authors: Karl MacMillan <kma...@me...>
+#
+# 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
+#
+
+# Parse interfaces and output extracted information about them
+# suitable for policy generation. By default writes the output
+# to the default location (obtained from sepolgen.defaults), but
+# will output to another file provided as an argument:
+# sepolgen-ifgen [headers] [output-filename]
+
+
+import sys
+import os
+
+import sepolgen.refparser as refparser
+import sepolgen.defaults as defaults
+import sepolgen.interfaces as interfaces
+
+
+VERSION = "%prog .1"
+
+def parse_options():
+ from optparse import OptionParser
+
+ parser = OptionParser(version=VERSION)
+ parser.add_option("-o", "--output", dest="output", default=defaults.interface_info(),
+ help="filename to store output")
+ parser.add_option("-i", "--interfaces", dest="headers", default=defaults.headers(),
+ help="location of the interface header files")
+ parser.add_option("-v", "--verbose", action="store_true", default=False,
+ help="print debuging output")
+ options, args = parser.parse_args()
+
+ return options
+
+
+def main():
+ options = parse_options()
+
+ # Open the output first to generate errors before parsing
+ try:
+ f = open(options.output, "w")
+ except IOError, e:
+ sys.stderr.write("could not open output file [%s]\n" % options.output)
+ return 1
+
+ if options.verbose:
+ log = sys.stdout
+ else:
+ log = None
+
+ try:
+ headers = refparser.parse_headers(options.headers, output=log)
+ except ValueError, e:
+ print "error parsing headers"
+ print str(e)
+ return 1
+
+ if_set = interfaces.InterfaceSet(output=log)
+ if_set.add_headers(headers)
+ if_set.to_file(f)
+ f.close()
+
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main())
Added: trunk/sepolgen/COPYING
===================================================================
--- trunk/sepolgen/COPYING (rev 0)
+++ trunk/sepolgen/COPYING 2007-02-05 19:01:07 UTC (rev 2220)
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 So...
[truncated message content] |