#! /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, 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, 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, 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())
