1#! /usr/bin/python -Es
2#
3# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
4#
5# Copyright (C) 2006 Red Hat 
6# see file 'COPYING' for use and warranty information
7#
8# This program is free software; you can redistribute it and/or
9# modify it under the terms of the GNU General Public License as
10# published by the Free Software Foundation; version 2 only
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20#
21
22# Parse interfaces and output extracted information about them
23# suitable for policy generation. By default writes the output
24# to the default location (obtained from sepolgen.defaults), but
25# will output to another file provided as an argument:
26#   sepolgen-ifgen [headers] [output-filename]
27
28
29import sys
30import os
31import tempfile
32import subprocess
33
34import selinux
35
36import sepolgen.refparser as refparser
37import sepolgen.defaults as defaults
38import sepolgen.interfaces as interfaces
39
40
41VERSION = "%prog .1"
42ATTR_HELPER = "/usr/bin/sepolgen-ifgen-attr-helper"
43
44def parse_options():
45    from optparse import OptionParser
46
47    parser = OptionParser(version=VERSION)
48    parser.add_option("-o", "--output", dest="output", default=defaults.interface_info(),
49                      help="filename to store output")
50    parser.add_option("-i", "--interfaces", dest="headers", default=defaults.headers(),
51                      help="location of the interface header files")
52    parser.add_option("-a", "--attribute_info", dest="attribute_info")
53    parser.add_option("-p", "--policy", dest="policy_path")
54    parser.add_option("-v", "--verbose", action="store_true", default=False,
55                      help="print debuging output")
56    parser.add_option("-d", "--debug", action="store_true", default=False,
57                     help="extra debugging output")
58    parser.add_option("--no_attrs", action="store_true", default=False,
59                      help="do not retrieve attribute access from kernel policy")
60    options, args = parser.parse_args()
61    
62    return options
63
64def get_policy():
65    p = selinux.selinux_current_policy_path()
66    if p and os.path.exists(p):
67        return p
68    i = selinux.security_policyvers()
69    p = selinux.selinux_binary_policy_path() + "." + str(i)
70    while i > 0 and not os.path.exists(p):
71        i = i - 1
72        p = selinux.selinux_binary_policy_path() + "." + str(i)
73    if i > 0:
74        return p
75    return None
76
77def get_attrs(policy_path):
78    try:
79        if not policy_path:
80            policy_path = get_policy()
81        if not policy_path:
82            sys.stderr.write("No installed policy to check\n")
83            return None
84        outfile = tempfile.NamedTemporaryFile()
85    except IOError, e:
86        sys.stderr.write("could not open attribute output file\n")
87        return None
88    except OSError:
89        # SELinux Disabled Machine
90        return None
91
92    fd = open("/dev/null","w")
93    ret = subprocess.Popen([ATTR_HELPER, policy_path, outfile.name], stdout=fd).wait()
94    fd.close()
95    if ret != 0:
96        sys.stderr.write("could not run attribute helper")
97        return None
98
99    attrs = interfaces.AttributeSet()
100    try:
101        attrs.from_file(outfile)
102    except:
103        print "error parsing attribute info"
104        return None
105
106    return attrs
107
108def main():
109    options = parse_options()
110
111    # Open the output first to generate errors before parsing
112    try:
113        f = open(options.output, "w")
114    except IOError, e:
115        sys.stderr.write("could not open output file [%s]\n" % options.output)
116        return 1
117
118    if options.verbose:
119        log = sys.stdout
120    else:
121        log = None
122
123    # Get the attibutes from the binary
124    attrs = None
125    if not options.no_attrs:
126        attrs = get_attrs(options.policy_path)
127        if attrs is None:
128            return 1
129
130    # Parse the headers
131    try:
132        headers = refparser.parse_headers(options.headers, output=log, debug=options.debug)
133    except ValueError, e:
134        print "error parsing headers"
135        print str(e)
136        return 1
137
138    if_set = interfaces.InterfaceSet(output=log)
139    if_set.add_headers(headers, attributes=attrs)
140    if_set.to_file(f)
141    f.close()
142
143    if refparser.success:
144        return 0
145    else:
146        return 1
147    
148if __name__ == "__main__":
149    sys.exit(main())
150