xref: /aosp_15_r20/external/selinux/python/sepolicy/sepolicy/interface.py (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1# Copyright (C) 2012 Red Hat
2# see file 'COPYING' for use and warranty information
3#
4# policygentool is a tool for the initial generation of SELinux policy
5#
6#    This program is free software; you can redistribute it and/or
7#    modify it under the terms of the GNU General Public License as
8#    published by the Free Software Foundation; either version 2 of
9#    the License, or (at your option) any later version.
10#
11#    This program is distributed in the hope that it will be useful,
12#    but WITHOUT ANY WARRANTY; without even the implied warranty of
13#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14#    GNU General Public License for more details.
15#
16#    You should have received a copy of the GNU General Public License
17#    along with this program; if not, write to the Free Software
18#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19#                                        02111-1307  USA
20#
21#
22import re
23import sys
24import sepolicy
25ADMIN_TRANSITION_INTERFACE = "_admin$"
26USER_TRANSITION_INTERFACE = "_role$"
27
28__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']
29
30##
31## I18N
32##
33PROGNAME = "selinux-python"
34try:
35    import gettext
36    kwargs = {}
37    if sys.version_info < (3,):
38        kwargs['unicode'] = True
39    t = gettext.translation(PROGNAME,
40                    localedir="/usr/share/locale",
41                    **kwargs,
42                    fallback=True)
43    _ = t.gettext
44except:
45    try:
46        import builtins
47        builtins.__dict__['_'] = str
48    except ImportError:
49        import __builtin__
50        __builtin__.__dict__['_'] = unicode
51
52
53def get_interfaces_from_xml(path):
54    """ Get all interfaces from given xml file"""
55    interfaces_list = []
56    idict = get_interface_dict(path)
57    for k in idict.keys():
58        interfaces_list.append(k)
59    return interfaces_list
60
61
62def get_all_interfaces(path=""):
63    from sepolicy import get_methods
64    all_interfaces = []
65    if not path:
66        all_interfaces = get_methods()
67    else:
68        xml_path = get_xml_file(path)
69        all_interfaces = get_interfaces_from_xml(xml_path)
70
71    return all_interfaces
72
73
74def get_admin(path=""):
75    """ Get all domains with an admin interface from installed policy."""
76    """ If xml_path is specified, func returns an admin interface from specified xml file"""
77    admin_list = []
78    if path:
79        try:
80            xml_path = get_xml_file(path)
81            idict = get_interface_dict(xml_path)
82            for k in idict.keys():
83                if k.endswith("_admin"):
84                    admin_list.append(k)
85        except IOError as e:
86            sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e)))
87            sys.exit(1)
88    else:
89        for i in sepolicy.get_methods():
90            if i.endswith("_admin"):
91                admin_list.append(i.split("_admin")[0])
92
93    return admin_list
94
95
96def get_user(path=""):
97    """ Get all domains with SELinux user role interface"""
98    """ If xml_path is specified, func returns an user role interface from specified xml file"""
99    trans_list = []
100    if path:
101        try:
102            xml_path = get_xml_file(path)
103            idict = get_interface_dict(xml_path)
104            for k in idict.keys():
105                if k.endswith("_role"):
106                    if (("%s_exec_t" % k[:-5]) in sepolicy.get_all_types()):
107                        trans_list.append(k)
108        except IOError as e:
109            sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e)))
110            sys.exit(1)
111    else:
112        for i in sepolicy.get_methods():
113            m = re.findall("(.*)%s" % USER_TRANSITION_INTERFACE, i)
114            if len(m) > 0:
115                if "%s_exec_t" % m[0] in sepolicy.get_all_types():
116                    trans_list.append(m[0])
117
118    return trans_list
119
120interface_dict = None
121
122
123def get_interface_dict(path="/usr/share/selinux/devel/policy.xml"):
124    global interface_dict
125    import os
126    import xml.etree.ElementTree
127    if interface_dict:
128        return interface_dict
129
130    interface_dict = {}
131    param_list = []
132
133    xml_path = """<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
134<policy>
135<layer name="admin">
136"""
137    xml_path += path
138    xml_path += """
139</layer>
140</policy>
141"""
142
143    try:
144        if os.path.isfile(path):
145            tree = xml.etree.ElementTree.parse(path)
146        else:
147            tree = xml.etree.ElementTree.fromstring(xml_path)
148        for l in tree.findall("layer"):
149            for m in l.findall("module"):
150                for i in m.iter('interface'):
151                    for e in i.findall("param"):
152                        param_list.append(e.get('name'))
153                    interface_dict[(i.get("name"))] = [param_list, (i.find('summary').text), "interface"]
154                    param_list = []
155                for i in m.iter('template'):
156                    for e in i.findall("param"):
157                        param_list.append(e.get('name'))
158                    interface_dict[(i.get("name"))] = [param_list, (i.find('summary').text), "template"]
159                    param_list = []
160    except IOError:
161        pass
162    return interface_dict
163
164
165def get_interface_format_text(interface, path="/usr/share/selinux/devel/policy.xml"):
166    idict = get_interface_dict(path)
167    interface_text = "%s(%s) %s" % (interface, ", ".join(idict[interface][0]), " ".join(idict[interface][1].split("\n")))
168
169    return interface_text
170
171
172def get_interface_compile_format_text(interfaces_dict, interface):
173    from .templates import test_module
174    param_tmp = []
175    for i in interfaces_dict[interface][0]:
176        param_tmp.append(test_module.dict_values[i])
177        interface_text = "%s(%s)\n" % (interface, ", ".join(param_tmp))
178
179    return interface_text
180
181
182def generate_compile_te(interface, idict, name="compiletest"):
183    from .templates import test_module
184    te = ""
185    te += re.sub("TEMPLATETYPE", name, test_module.te_test_module)
186    te += get_interface_compile_format_text(idict, interface)
187
188    return te
189
190
191def get_xml_file(if_file):
192    """ Returns xml format of interfaces for given .if policy file"""
193    import os
194    try:
195        from commands import getstatusoutput
196    except ImportError:
197        from subprocess import getstatusoutput
198    basedir = os.path.dirname(if_file) + "/"
199    filename = os.path.basename(if_file).split(".")[0]
200    rc, output = getstatusoutput("/usr/bin/python3 /usr/share/selinux/devel/include/support/segenxml.py -w -m %s" % (basedir + filename))
201    if rc != 0:
202        sys.stderr.write("\n Could not process selected interface file.\n")
203        sys.stderr.write("\n%s" % output)
204        sys.exit(1)
205    else:
206        return output
207
208
209def interface_compile_test(interface, path="/usr/share/selinux/devel/policy.xml"):
210    exclude_interfaces = ["userdom", "kernel", "corenet", "files", "dev"]
211    exclude_interface_type = ["template"]
212
213    try:
214        from commands import getstatusoutput
215    except ImportError:
216        from subprocess import getstatusoutput
217    import os
218    policy_files = {'pp': "compiletest.pp", 'te': "compiletest.te", 'fc': "compiletest.fc", 'if': "compiletest.if"}
219    idict = get_interface_dict(path)
220
221    if not (interface.split("_")[0] in exclude_interfaces or idict[interface][2] in exclude_interface_type):
222        print(_("Compiling %s interface") % interface)
223        try:
224            fd = open(policy_files['te'], "w")
225            fd.write(generate_compile_te(interface, idict))
226            fd.close()
227            rc, output = getstatusoutput("make -f /usr/share/selinux/devel/Makefile %s" % policy_files['pp'])
228            if rc != 0:
229                sys.stderr.write(output)
230                sys.stderr.write(_("\nCompile test for %s failed.\n") % interface)
231
232        except EnvironmentError as e:
233            sys.stderr.write(_("\nCompile test for %s has not run. %s\n") % (interface, e))
234        for v in policy_files.values():
235            if os.path.exists(v):
236                os.remove(v)
237
238    else:
239        sys.stderr.write(_("\nCompiling of %s interface is not supported.") % interface)
240