#!/usr/bin/python -Es
#
# Copyright (C) 2012 Red Hat
# see file 'COPYING' for use and warranty information
#
# policygentool is a tool for the initial generation of SELinux policy
#
#    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 re
import sys
import sepolicy
ADMIN_TRANSITION_INTERFACE = "_admin$"
USER_TRANSITION_INTERFACE = "_role$"

__all__ = ['get_all_interfaces', 'get_interfaces_from_xml', 'get_admin', 'get_user', 'get_interface_dict', 'get_interface_format_text', 'get_interface_compile_format_text', 'get_xml_file', 'interface_compile_test']

##
## I18N
##
PROGNAME = "policycoreutils"

import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
gettext.textdomain(PROGNAME)
try:
    gettext.install(PROGNAME,
                    localedir="/usr/share/locale",
                    unicode=False,
                    codeset='utf-8')
except IOError:
    import __builtin__
    __builtin__.__dict__['_'] = unicode


def get_interfaces_from_xml(path):
    """ Get all interfaces from given xml file"""
    interfaces_list = []
    idict = get_interface_dict(path)
    for k in idict.keys():
        interfaces_list.append(k)
    return interfaces_list


def get_all_interfaces(path=""):
    from sepolicy import get_methods
    all_interfaces = []
    if not path:
        all_interfaces = get_methods()
    else:
        xml_path = get_xml_file(path)
        all_interfaces = get_interfaces_from_xml(xml_path)

    return all_interfaces


def get_admin(path=""):
    """ Get all domains with an admin interface from installed policy."""
    """ If xml_path is specified, func returns an admin interface from specified xml file"""
    admin_list = []
    if path:
        try:
            xml_path = get_xml_file(path)
            idict = get_interface_dict(xml_path)
            for k in idict.keys():
                if k.endswith("_admin"):
                    admin_list.append(k)
        except IOError, e:
            sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e)))
            sys.exit(1)
    else:
        for i in sepolicy.get_methods():
            if i.endswith("_admin"):
                admin_list.append(i.split("_admin")[0])

    return admin_list


def get_user(path=""):
    """ Get all domains with SELinux user role interface"""
    """ If xml_path is specified, func returns an user role interface from specified xml file"""
    trans_list = []
    if path:
        try:
            xml_path = get_xml_file(path)
            idict = get_interface_dict(xml_path)
            for k in idict.keys():
                if k.endswith("_role"):
                    if (("%s_exec_t" % k[:-5]) in sepolicy.get_all_types()):
                        trans_list.append(k)
        except IOError, e:
            sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e)))
            sys.exit(1)
    else:
        for i in sepolicy.get_methods():
            m = re.findall("(.*)%s" % USER_TRANSITION_INTERFACE, i)
            if len(m) > 0:
                if "%s_exec_t" % m[0] in sepolicy.get_all_types():
                    trans_list.append(m[0])

    return trans_list

interface_dict = None


def get_interface_dict(path="/usr/share/selinux/devel/policy.xml"):
    global interface_dict
    import os
    import xml.etree.ElementTree
    if interface_dict:
        return interface_dict

    interface_dict = {}
    param_list = []

    xml_path = """<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<policy>
<layer name="admin">
"""
    xml_path += path
    xml_path += """
</layer>
</policy>
"""

    try:
        if os.path.isfile(path):
            tree = xml.etree.ElementTree.parse(path)
        else:
            tree = xml.etree.ElementTree.fromstring(xml_path)
        for l in tree.findall("layer"):
            for m in l.findall("module"):
                for i in m.getiterator('interface'):
                    for e in i.findall("param"):
                        param_list.append(e.get('name'))
                    interface_dict[(i.get("name"))] = [param_list, (i.find('summary').text), "interface"]
                    param_list = []
                for i in m.getiterator('template'):
                    for e in i.findall("param"):
                        param_list.append(e.get('name'))
                    interface_dict[(i.get("name"))] = [param_list, (i.find('summary').text), "template"]
                    param_list = []
    except IOError, e:
        pass
    return interface_dict


def get_interface_format_text(interface, path="/usr/share/selinux/devel/policy.xml"):
    idict = get_interface_dict(path)
    interface_text = "%s(%s) %s" % (interface, ", ".join(idict[interface][0]), " ".join(idict[interface][1].split("\n")))

    return interface_text


def get_interface_compile_format_text(interfaces_dict, interface):
    from templates import test_module
    param_tmp = []
    for i in interfaces_dict[interface][0]:
        param_tmp.append(test_module.dict_values[i])
        interface_text = "%s(%s)\n" % (interface, ", ".join(param_tmp))

    return interface_text


def generate_compile_te(interface, idict, name="compiletest"):
    from templates import test_module
    te = ""
    te += re.sub("TEMPLATETYPE", name, test_module.te_test_module)
    te += get_interface_compile_format_text(idict, interface)

    return te


def get_xml_file(if_file):
    """ Returns xml format of interfaces for given .if policy file"""
    import os
    import commands
    basedir = os.path.dirname(if_file) + "/"
    filename = os.path.basename(if_file).split(".")[0]
    rc, output = commands.getstatusoutput("python /usr/share/selinux/devel/include/support/segenxml.py -w -m %s" % basedir + filename)
    if rc != 0:
        sys.stderr.write("\n Could not proceed selected interface file.\n")
        sys.stderr.write("\n%s" % output)
        sys.exit(1)
    else:
        return output


def interface_compile_test(interface, path="/usr/share/selinux/devel/policy.xml"):
    exclude_interfaces = ["userdom", "kernel", "corenet", "files", "dev"]
    exclude_interface_type = ["template"]

    import commands
    import os
    policy_files = {'pp': "compiletest.pp", 'te': "compiletest.te", 'fc': "compiletest.fc", 'if': "compiletest.if"}
    idict = get_interface_dict(path)

    if not (interface.split("_")[0] in exclude_interfaces or idict[interface][2] in exclude_interface_type):
        print(_("Compiling %s interface" % interface))
        try:
            fd = open(policy_files['te'], "w")
            fd.write(generate_compile_te(interface, idict))
            fd.close()
            rc, output = commands.getstatusoutput("make -f /usr/share/selinux/devel/Makefile %s" % policy_files['pp'])
            if rc != 0:
                sys.stderr.write(output)
                sys.stderr.write(_("\nCompile test for %s failed.\n") % interface)

        except EnvironmentError, e:
            sys.stderr.write(_("\nCompile test for %s has not run. %s\n") % (interface, e))
        for v in policy_files.values():
            if os.path.exists(v):
                os.remove(v)

    else:
        sys.stderr.write(_("\nCompiling of %s interface is not supported." % interface))
