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
44
45def parse_options():
46    from optparse import OptionParser
47
48    parser = OptionParser(version=VERSION)
49    parser.add_option("-o", "--output", dest="output", default=defaults.interface_info(),
50                      help="filename to store output")
51    parser.add_option("-i", "--interfaces", dest="headers", default=defaults.headers(),
52                      help="location of the interface header files")
53    parser.add_option("-a", "--attribute_info", dest="attribute_info")
54    parser.add_option("-p", "--policy", dest="policy_path")
55    parser.add_option("-v", "--verbose", action="store_true", default=False,
56                      help="print debuging output")
57    parser.add_option("-d", "--debug", action="store_true", default=False,
58                      help="extra debugging output")
59    parser.add_option("--no_attrs", action="store_true", default=False,
60                      help="do not retrieve attribute access from kernel policy")
61    options, args = parser.parse_args()
62
63    return options
64
65
66def get_policy():
67    p = selinux.selinux_current_policy_path()
68    if p and os.path.exists(p):
69        return p
70    i = selinux.security_policyvers()
71    p = selinux.selinux_binary_policy_path() + "." + str(i)
72    while i > 0 and not os.path.exists(p):
73        i = i - 1
74        p = selinux.selinux_binary_policy_path() + "." + str(i)
75    if i > 0:
76        return p
77    return None
78
79
80def get_attrs(policy_path):
81    try:
82        if not policy_path:
83            policy_path = get_policy()
84        if not policy_path:
85            sys.stderr.write("No installed policy to check\n")
86            return None
87        outfile = tempfile.NamedTemporaryFile()
88    except IOError as e:
89        sys.stderr.write("could not open attribute output file\n")
90        return None
91    except OSError:
92        # SELinux Disabled Machine
93        return None
94
95    fd = open("/dev/null", "w")
96    ret = subprocess.Popen([ATTR_HELPER, policy_path, outfile.name], stdout=fd).wait()
97    fd.close()
98    if ret != 0:
99        sys.stderr.write("could not run attribute helper")
100        return None
101
102    attrs = interfaces.AttributeSet()
103    try:
104        attrs.from_file(outfile)
105    except:
106        print("error parsing attribute info")
107        return None
108
109    return attrs
110
111
112def main():
113    options = parse_options()
114
115    # Open the output first to generate errors before parsing
116    try:
117        f = open(options.output, "w")
118    except IOError as e:
119        sys.stderr.write("could not open output file [%s]\n" % options.output)
120        return 1
121
122    if options.verbose:
123        log = sys.stdout
124    else:
125        log = None
126
127    # Get the attibutes from the binary
128    attrs = None
129    if not options.no_attrs:
130        attrs = get_attrs(options.policy_path)
131        if attrs is None:
132            return 1
133
134    # Parse the headers
135    try:
136        headers = refparser.parse_headers(options.headers, output=log, debug=options.debug)
137    except ValueError as e:
138        print("error parsing headers")
139        print(str(e))
140        return 1
141
142    if_set = interfaces.InterfaceSet(output=log)
143    if_set.add_headers(headers, attributes=attrs)
144    if_set.to_file(f)
145    f.close()
146
147    if refparser.success:
148        return 0
149    else:
150        return 1
151
152if __name__ == "__main__":
153    sys.exit(main())
154