#! /usr/bin/python -Es
#
# 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
#

# 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 tempfile
import subprocess

import selinux

import sepolgen.refparser as refparser
import sepolgen.defaults as defaults
import sepolgen.interfaces as interfaces


VERSION = "%prog .1"
ATTR_HELPER = "/usr/bin/sepolgen-ifgen-attr-helper"


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("-a", "--attribute_info", dest="attribute_info")
    parser.add_option("-p", "--policy", dest="policy_path")
    parser.add_option("-v", "--verbose", action="store_true", default=False,
                      help="print debuging output")
    parser.add_option("-d", "--debug", action="store_true", default=False,
                      help="extra debugging output")
    parser.add_option("--no_attrs", action="store_true", default=False,
                      help="do not retrieve attribute access from kernel policy")
    options, args = parser.parse_args()

    return options


def get_policy():
    p = selinux.selinux_current_policy_path()
    if p and os.path.exists(p):
        return p
    i = selinux.security_policyvers()
    p = selinux.selinux_binary_policy_path() + "." + str(i)
    while i > 0 and not os.path.exists(p):
        i = i - 1
        p = selinux.selinux_binary_policy_path() + "." + str(i)
    if i > 0:
        return p
    return None


def get_attrs(policy_path):
    try:
        if not policy_path:
            policy_path = get_policy()
        if not policy_path:
            sys.stderr.write("No installed policy to check\n")
            return None
        outfile = tempfile.NamedTemporaryFile()
    except IOError as e:
        sys.stderr.write("could not open attribute output file\n")
        return None
    except OSError:
        # SELinux Disabled Machine
        return None

    fd = open("/dev/null", "w")
    ret = subprocess.Popen([ATTR_HELPER, policy_path, outfile.name], stdout=fd).wait()
    fd.close()
    if ret != 0:
        sys.stderr.write("could not run attribute helper")
        return None

    attrs = interfaces.AttributeSet()
    try:
        attrs.from_file(outfile)
    except:
        print("error parsing attribute info")
        return None

    return attrs


def main():
    options = parse_options()

    # Open the output first to generate errors before parsing
    try:
        f = open(options.output, "w")
    except IOError as e:
        sys.stderr.write("could not open output file [%s]\n" % options.output)
        return 1

    if options.verbose:
        log = sys.stdout
    else:
        log = None

    # Get the attibutes from the binary
    attrs = None
    if not options.no_attrs:
        attrs = get_attrs(options.policy_path)
        if attrs is None:
            return 1

    # Parse the headers
    try:
        headers = refparser.parse_headers(options.headers, output=log, debug=options.debug)
    except ValueError as e:
        print("error parsing headers")
        print(str(e))
        return 1

    if_set = interfaces.InterfaceSet(output=log)
    if_set.add_headers(headers, attributes=attrs)
    if_set.to_file(f)
    f.close()

    if refparser.success:
        return 0
    else:
        return 1

if __name__ == "__main__":
    sys.exit(main())
