xref: /aosp_15_r20/external/selinux/gui/polgengui.py (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1#!/usr/bin/python3 -EsI
2#
3# polgengui.py - GUI for SELinux Config tool in system-config-selinux
4#
5# Dan Walsh <[email protected]>
6#
7# Copyright (C) 2007-2013 Red Hat
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22#
23import signal
24import string
25import gi
26gi.require_version('Gtk', '3.0')
27from gi.repository import Gtk
28import os
29from gi.repository import GObject
30import sys
31try:
32    import sepolicy
33except ValueError as e:
34    sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e)))
35    sys.exit(1)
36
37import sepolicy.generate
38import sepolicy.interface
39
40try:
41    from subprocess import getstatusoutput
42except ImportError:
43    from commands import getstatusoutput
44
45
46import re
47
48
49def get_all_modules():
50    try:
51        all_modules = []
52        rc, output = getstatusoutput("semodule -l 2>/dev/null")
53        if rc == 0:
54            l = output.split("\n")
55            for i in l:
56                all_modules.append(i.split()[0])
57    except:
58        pass
59
60    return all_modules
61
62
63##
64## I18N
65##
66PROGNAME = "selinux-gui"
67try:
68    import gettext
69    kwargs = {}
70    if sys.version_info < (3,):
71        kwargs['unicode'] = True
72    t = gettext.translation(PROGNAME,
73                    localedir="/usr/share/locale",
74                    **kwargs,
75                    fallback=True)
76    _ = t.gettext
77except:
78    try:
79        import builtins
80        builtins.__dict__['_'] = str
81    except ImportError:
82        import __builtin__
83        __builtin__.__dict__['_'] = unicode
84
85version = "1.0"
86
87sys.path.append('/usr/share/system-config-selinux')
88sys.path.append('.')
89
90# From John Hunter http://www.daa.com.au/pipermail/pygtk/2003-February/004454.html
91
92
93def foreach(model, path, iter, selected):
94    selected.append(model.get_value(iter, 0))
95
96##
97## Pull in the Glade file
98##
99xml = Gtk.Builder()
100xml.set_translation_domain(PROGNAME)
101if os.access("polgen.ui", os.F_OK):
102    xml.add_from_file("polgen.ui")
103else:
104    xml.add_from_file("/usr/share/system-config-selinux/polgen.ui")
105
106FILE = 1
107DIR = 2
108
109
110class childWindow:
111    START_PAGE = 0
112    SELECT_TYPE_PAGE = 0
113    APP_PAGE = 1
114    EXISTING_USER_PAGE = 2
115    TRANSITION_PAGE = 3
116    USER_TRANSITION_PAGE = 4
117    ADMIN_PAGE = 5
118    ROLE_PAGE = 6
119    IN_NET_PAGE = 7
120    OUT_NET_PAGE = 8
121    COMMON_APPS_PAGE = 9
122    FILES_PAGE = 10
123    BOOLEAN_PAGE = 11
124    SELECT_DIR_PAGE = 12
125    FINISH_PAGE = 12
126
127    def __init__(self):
128        self.xml = xml
129        self.notebook = xml.get_object("notebook")
130        self.label_dict = {}
131        self.tooltip_dict = {}
132        label = xml.get_object("select_label")
133        self.label_dict[label] = label.get_text()
134
135        label = xml.get_object("select_user_roles_label")
136        self.label_dict[label] = label.get_text()
137
138        label = xml.get_object("select_dir_label")
139        self.label_dict[label] = label.get_text()
140
141        label = xml.get_object("select_domain_admin_label")
142        self.label_dict[label] = label.get_text()
143
144        label = xml.get_object("select_in_label")
145        self.label_dict[label] = label.get_text()
146
147        label = xml.get_object("select_out_label")
148        self.label_dict[label] = label.get_text()
149
150        label = xml.get_object("select_common_label")
151        self.label_dict[label] = label.get_text()
152
153        label = xml.get_object("select_manages_label")
154        self.label_dict[label] = label.get_text()
155
156        label = xml.get_object("select_booleans_label")
157        self.label_dict[label] = label.get_text()
158
159        label = xml.get_object("existing_user_treeview")
160        self.tooltip_dict[label] = label.get_tooltip_text()
161
162        label = xml.get_object("transition_treeview")
163        self.tooltip_dict[label] = label.get_tooltip_text()
164
165        label = xml.get_object("in_tcp_all_checkbutton")
166        self.tooltip_dict[label] = label.get_tooltip_text()
167
168        label = xml.get_object("in_tcp_reserved_checkbutton")
169        self.tooltip_dict[label] = label.get_tooltip_text()
170
171        label = xml.get_object("in_tcp_unreserved_checkbutton")
172        self.tooltip_dict[label] = label.get_tooltip_text()
173
174        label = xml.get_object("in_tcp_entry")
175        self.tooltip_dict[label] = label.get_tooltip_text()
176
177        label = xml.get_object("in_udp_all_checkbutton")
178        self.tooltip_dict[label] = label.get_tooltip_text()
179
180        label = xml.get_object("in_udp_reserved_checkbutton")
181        self.tooltip_dict[label] = label.get_tooltip_text()
182
183        label = xml.get_object("in_udp_unreserved_checkbutton")
184        self.tooltip_dict[label] = label.get_tooltip_text()
185
186        label = xml.get_object("in_udp_entry")
187        self.tooltip_dict[label] = label.get_tooltip_text()
188
189        label = xml.get_object("out_tcp_entry")
190        self.tooltip_dict[label] = label.get_tooltip_text()
191
192        label = xml.get_object("out_udp_entry")
193        self.tooltip_dict[label] = label.get_tooltip_text()
194
195        label = xml.get_object("out_tcp_all_checkbutton")
196        self.tooltip_dict[label] = label.get_tooltip_text()
197
198        label = xml.get_object("out_udp_all_checkbutton")
199        self.tooltip_dict[label] = label.get_tooltip_text()
200
201        label = xml.get_object("boolean_treeview")
202        self.tooltip_dict[label] = label.get_tooltip_text()
203
204        label = xml.get_object("write_treeview")
205        self.tooltip_dict[label] = label.get_tooltip_text()
206
207        try:
208            self.all_types = sepolicy.generate.get_all_types()
209            self.all_modules = get_all_modules()
210            self.all_roles = sepolicy.generate.get_all_roles()
211            self.all_users = sepolicy.generate.get_all_users()
212        except RuntimeError as e:
213            self.all_types = []
214            self.all_modules = []
215            self.all_roles = []
216            self.all_users = []
217            self.error(str(e))
218
219        self.name = ""
220        handlers = {
221            "on_delete_clicked": self.delete,
222            "on_delete_boolean_clicked": self.delete_boolean,
223            "on_exec_select_clicked": self.exec_select,
224            "on_init_script_select_clicked": self.init_script_select,
225            "on_add_clicked": self.add,
226            "on_add_boolean_clicked": self.add_boolean,
227            "on_add_dir_clicked": self.add_dir,
228            "on_about_clicked": self.on_about_clicked
229        }
230        xml.connect_signals(handlers)
231        xml.get_object("cancel_button").connect("clicked", self.quit)
232        self.forward_button = xml.get_object("forward_button")
233        self.forward_button.connect("clicked", self.forward)
234        self.back_button = xml.get_object("back_button")
235        self.back_button.connect("clicked", self.back)
236
237        self.boolean_dialog = xml.get_object("boolean_dialog")
238        self.boolean_name_entry = xml.get_object("boolean_name_entry")
239        self.boolean_description_entry = xml.get_object("boolean_description_entry")
240
241        self.pages = {}
242        for i in sepolicy.generate.USERS:
243            self.pages[i] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.TRANSITION_PAGE, self.ROLE_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
244        self.pages[sepolicy.generate.RUSER] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.ADMIN_PAGE, self.USER_TRANSITION_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
245        self.pages[sepolicy.generate.LUSER] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.TRANSITION_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
246        self.pages[sepolicy.generate.SANDBOX] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
247        self.pages[sepolicy.generate.EUSER] = [self.SELECT_TYPE_PAGE, self.EXISTING_USER_PAGE, self.TRANSITION_PAGE, self.ROLE_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
248
249        for i in sepolicy.generate.APPLICATIONS:
250            self.pages[i] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.COMMON_APPS_PAGE, self.FILES_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
251        self.pages[sepolicy.generate.USER] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.USER_TRANSITION_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.COMMON_APPS_PAGE, self.FILES_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
252
253        self.current_page = 0
254        self.back_button.set_sensitive(0)
255
256        self.network_buttons = {}
257
258        self.in_tcp_all_checkbutton = xml.get_object("in_tcp_all_checkbutton")
259        self.in_tcp_reserved_checkbutton = xml.get_object("in_tcp_reserved_checkbutton")
260        self.in_tcp_unreserved_checkbutton = xml.get_object("in_tcp_unreserved_checkbutton")
261        self.in_tcp_entry = self.xml.get_object("in_tcp_entry")
262        self.network_buttons[self.in_tcp_all_checkbutton] = [self.in_tcp_reserved_checkbutton, self.in_tcp_unreserved_checkbutton, self.in_tcp_entry]
263
264        self.out_tcp_all_checkbutton = xml.get_object("out_tcp_all_checkbutton")
265        self.out_tcp_reserved_checkbutton = xml.get_object("out_tcp_reserved_checkbutton")
266        self.out_tcp_unreserved_checkbutton = xml.get_object("out_tcp_unreserved_checkbutton")
267        self.out_tcp_entry = self.xml.get_object("out_tcp_entry")
268
269        self.network_buttons[self.out_tcp_all_checkbutton] = [self.out_tcp_entry]
270
271        self.in_udp_all_checkbutton = xml.get_object("in_udp_all_checkbutton")
272        self.in_udp_reserved_checkbutton = xml.get_object("in_udp_reserved_checkbutton")
273        self.in_udp_unreserved_checkbutton = xml.get_object("in_udp_unreserved_checkbutton")
274        self.in_udp_entry = self.xml.get_object("in_udp_entry")
275
276        self.network_buttons[self.in_udp_all_checkbutton] = [self.in_udp_reserved_checkbutton, self.in_udp_unreserved_checkbutton, self.in_udp_entry]
277
278        self.out_udp_all_checkbutton = xml.get_object("out_udp_all_checkbutton")
279        self.out_udp_entry = self.xml.get_object("out_udp_entry")
280        self.network_buttons[self.out_udp_all_checkbutton] = [self.out_udp_entry]
281
282        for b in self.network_buttons.keys():
283            b.connect("clicked", self.network_all_clicked)
284
285        self.boolean_treeview = self.xml.get_object("boolean_treeview")
286        self.boolean_store = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING)
287        self.boolean_treeview.set_model(self.boolean_store)
288        self.boolean_store.set_sort_column_id(0, Gtk.SortType.ASCENDING)
289        col = Gtk.TreeViewColumn(_("Name"), Gtk.CellRendererText(), text=0)
290        self.boolean_treeview.append_column(col)
291        col = Gtk.TreeViewColumn(_("Description"), Gtk.CellRendererText(), text=1)
292        self.boolean_treeview.append_column(col)
293
294        self.role_treeview = self.xml.get_object("role_treeview")
295        self.role_store = Gtk.ListStore(GObject.TYPE_STRING)
296        self.role_treeview.set_model(self.role_store)
297        self.role_treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE)
298        self.role_store.set_sort_column_id(0, Gtk.SortType.ASCENDING)
299        col = Gtk.TreeViewColumn(_("Role"), Gtk.CellRendererText(), text=0)
300        self.role_treeview.append_column(col)
301
302        self.existing_user_treeview = self.xml.get_object("existing_user_treeview")
303        self.existing_user_store = Gtk.ListStore(GObject.TYPE_STRING)
304        self.existing_user_treeview.set_model(self.existing_user_store)
305        self.existing_user_store.set_sort_column_id(0, Gtk.SortType.ASCENDING)
306        col = Gtk.TreeViewColumn(_("Existing_User"), Gtk.CellRendererText(), text=0)
307        self.existing_user_treeview.append_column(col)
308
309        for i in self.all_roles:
310            iter = self.role_store.append()
311            self.role_store.set_value(iter, 0, i[:-2])
312
313        self.in_tcp_reserved_checkbutton = xml.get_object("in_tcp_reserved_checkbutton")
314
315        self.transition_treeview = self.xml.get_object("transition_treeview")
316        self.transition_store = Gtk.ListStore(GObject.TYPE_STRING)
317        self.transition_treeview.set_model(self.transition_store)
318        self.transition_treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE)
319        self.transition_store.set_sort_column_id(0, Gtk.SortType.ASCENDING)
320        col = Gtk.TreeViewColumn(_("Application"), Gtk.CellRendererText(), text=0)
321        self.transition_treeview.append_column(col)
322
323        self.user_transition_treeview = self.xml.get_object("user_transition_treeview")
324        self.user_transition_store = Gtk.ListStore(GObject.TYPE_STRING)
325        self.user_transition_treeview.set_model(self.user_transition_store)
326        self.user_transition_treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE)
327        self.user_transition_store.set_sort_column_id(0, Gtk.SortType.ASCENDING)
328        col = Gtk.TreeViewColumn(_("Application"), Gtk.CellRendererText(), text=0)
329        self.user_transition_treeview.append_column(col)
330
331        for i in self.all_users:
332            iter = self.user_transition_store.append()
333            self.user_transition_store.set_value(iter, 0, i[:-2])
334            iter = self.existing_user_store.append()
335            self.existing_user_store.set_value(iter, 0, i[:-2])
336
337        self.admin_treeview = self.xml.get_object("admin_treeview")
338        self.admin_store = Gtk.ListStore(GObject.TYPE_STRING)
339        self.admin_treeview.set_model(self.admin_store)
340        self.admin_treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE)
341        self.admin_store.set_sort_column_id(0, Gtk.SortType.ASCENDING)
342        col = Gtk.TreeViewColumn(_("Application"), Gtk.CellRendererText(), text=0)
343        self.admin_treeview.append_column(col)
344
345        try:
346            for u in sepolicy.interface.get_user():
347                iter = self.transition_store.append()
348                self.transition_store.set_value(iter, 0, u)
349
350            for a in sepolicy.interface.get_admin():
351                iter = self.admin_store.append()
352                self.admin_store.set_value(iter, 0, a)
353        except ValueError as e:
354            self.error(e.message)
355
356    def confine_application(self):
357        return self.get_type() in sepolicy.generate.APPLICATIONS
358
359    def forward(self, arg):
360        type = self.get_type()
361        if self.current_page == self.START_PAGE:
362            self.back_button.set_sensitive(1)
363
364        if self.pages[type][self.current_page] == self.SELECT_TYPE_PAGE:
365            if self.on_select_type_page_next():
366                return
367
368        if self.pages[type][self.current_page] == self.IN_NET_PAGE:
369            if self.on_in_net_page_next():
370                return
371
372        if self.pages[type][self.current_page] == self.OUT_NET_PAGE:
373            if self.on_out_net_page_next():
374                return
375
376        if self.pages[type][self.current_page] == self.APP_PAGE:
377            if self.on_name_page_next():
378                return
379
380        if self.pages[type][self.current_page] == self.EXISTING_USER_PAGE:
381            if self.on_existing_user_page_next():
382                return
383
384        if self.pages[type][self.current_page] == self.SELECT_DIR_PAGE:
385            outputdir = self.output_entry.get_text()
386            if not os.path.isdir(outputdir):
387                self.error(_("%s must be a directory") % outputdir)
388                return False
389
390        if self.pages[type][self.current_page] == self.FINISH_PAGE:
391            self.generate_policy()
392            self.xml.get_object("cancel_button").set_label(Gtk.STOCK_CLOSE)
393        else:
394            self.current_page = self.current_page + 1
395            self.notebook.set_current_page(self.pages[type][self.current_page])
396            if self.pages[type][self.current_page] == self.FINISH_PAGE:
397                self.forward_button.set_label(Gtk.STOCK_APPLY)
398
399    def back(self, arg):
400        type = self.get_type()
401        if self.pages[type][self.current_page] == self.FINISH_PAGE:
402            self.forward_button.set_label(Gtk.STOCK_GO_FORWARD)
403
404        self.current_page = self.current_page - 1
405        self.notebook.set_current_page(self.pages[type][self.current_page])
406        if self.pages[type][self.current_page] == self.START_PAGE:
407            self.back_button.set_sensitive(0)
408
409    def network_all_clicked(self, button):
410        active = button.get_active()
411        for b in self.network_buttons[button]:
412            b.set_sensitive(not active)
413
414    def verify(self, message, title=""):
415        dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO,
416                                Gtk.ButtonsType.YES_NO,
417                                message)
418        dlg.set_title(title)
419        dlg.set_position(Gtk.WindowPosition.MOUSE)
420        dlg.show_all()
421        rc = dlg.run()
422        dlg.destroy()
423        return rc
424
425    def info(self, message):
426        dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO,
427                                Gtk.ButtonsType.OK,
428                                message)
429        dlg.set_position(Gtk.WindowPosition.MOUSE)
430        dlg.show_all()
431        dlg.run()
432        dlg.destroy()
433
434    def error(self, message):
435        dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.ERROR,
436                                Gtk.ButtonsType.CLOSE,
437                                message)
438        dlg.set_position(Gtk.WindowPosition.MOUSE)
439        dlg.show_all()
440        dlg.run()
441        dlg.destroy()
442
443    def get_name(self):
444        if self.existing_user_radiobutton.get_active():
445            store, iter = self.existing_user_treeview.get_selection().get_selected()
446            if iter == None:
447                raise ValueError(_("You must select a user"))
448            return store.get_value(iter, 0)
449        else:
450            return self.name_entry.get_text()
451
452    def get_type(self):
453        if self.sandbox_radiobutton.get_active():
454            return sepolicy.generate.SANDBOX
455        if self.cgi_radiobutton.get_active():
456            return sepolicy.generate.CGI
457        if self.user_radiobutton.get_active():
458            return sepolicy.generate.USER
459        if self.init_radiobutton.get_active():
460            return sepolicy.generate.DAEMON
461        if self.dbus_radiobutton.get_active():
462            return sepolicy.generate.DBUS
463        if self.inetd_radiobutton.get_active():
464            return sepolicy.generate.INETD
465        if self.login_user_radiobutton.get_active():
466            return sepolicy.generate.LUSER
467        if self.admin_user_radiobutton.get_active():
468            return sepolicy.generate.AUSER
469        if self.xwindows_user_radiobutton.get_active():
470            return sepolicy.generate.XUSER
471        if self.terminal_user_radiobutton.get_active():
472            return sepolicy.generate.TUSER
473        if self.root_user_radiobutton.get_active():
474            return sepolicy.generate.RUSER
475        if self.existing_user_radiobutton.get_active():
476            return sepolicy.generate.EUSER
477
478    def generate_policy(self, *args):
479        outputdir = self.output_entry.get_text()
480        try:
481            my_policy = sepolicy.generate.policy(self.get_name(), self.get_type())
482
483            iter = self.boolean_store.get_iter_first()
484            while iter:
485                my_policy.add_boolean(self.boolean_store.get_value(iter, 0), self.boolean_store.get_value(iter, 1))
486                iter = self.boolean_store.iter_next(iter)
487
488            if self.get_type() in sepolicy.generate.APPLICATIONS:
489                my_policy.set_program(self.exec_entry.get_text())
490                my_policy.gen_symbols()
491
492                my_policy.set_use_syslog(self.syslog_checkbutton.get_active() == 1)
493                my_policy.set_use_tmp(self.tmp_checkbutton.get_active() == 1)
494                my_policy.set_use_uid(self.uid_checkbutton.get_active() == 1)
495                my_policy.set_use_pam(self.pam_checkbutton.get_active() == 1)
496
497                my_policy.set_use_dbus(self.dbus_checkbutton.get_active() == 1)
498                my_policy.set_use_audit(self.audit_checkbutton.get_active() == 1)
499                my_policy.set_use_terminal(self.terminal_checkbutton.get_active() == 1)
500                my_policy.set_use_mail(self.mail_checkbutton.get_active() == 1)
501                if self.get_type() is sepolicy.generate.DAEMON:
502                    my_policy.set_init_script(self.init_script_entry.get_text())
503                if self.get_type() == sepolicy.generate.USER:
504                    selected = []
505                    self.user_transition_treeview.get_selection().selected_foreach(foreach, selected)
506                    my_policy.set_transition_users(selected)
507            else:
508                if self.get_type() == sepolicy.generate.RUSER:
509                    selected = []
510                    self.admin_treeview.get_selection().selected_foreach(foreach, selected)
511                    my_policy.set_admin_domains(selected)
512                    selected = []
513                    self.user_transition_treeview.get_selection().selected_foreach(foreach, selected)
514                    my_policy.set_transition_users(selected)
515                else:
516                    selected = []
517                    self.transition_treeview.get_selection().selected_foreach(foreach, selected)
518                    my_policy.set_transition_domains(selected)
519
520                    selected = []
521                    self.role_treeview.get_selection().selected_foreach(foreach, selected)
522                    my_policy.set_admin_roles(selected)
523
524            my_policy.set_in_tcp(self.in_tcp_all_checkbutton.get_active(), self.in_tcp_reserved_checkbutton.get_active(), self.in_tcp_unreserved_checkbutton.get_active(), self.in_tcp_entry.get_text())
525            my_policy.set_in_udp(self.in_udp_all_checkbutton.get_active(), self.in_udp_reserved_checkbutton.get_active(), self.in_udp_unreserved_checkbutton.get_active(), self.in_udp_entry.get_text())
526            my_policy.set_out_tcp(self.out_tcp_all_checkbutton.get_active(), self.out_tcp_entry.get_text())
527            my_policy.set_out_udp(self.out_udp_all_checkbutton.get_active(), self.out_udp_entry.get_text())
528
529            iter = self.store.get_iter_first()
530            while iter:
531                if self.store.get_value(iter, 1) == FILE:
532                    my_policy.add_file(self.store.get_value(iter, 0))
533                else:
534                    my_policy.add_dir(self.store.get_value(iter, 0))
535                iter = self.store.iter_next(iter)
536
537            self.info(my_policy.generate(outputdir))
538            return False
539        except ValueError as e:
540            self.error(e.message)
541
542    def delete(self, args):
543        store, iter = self.view.get_selection().get_selected()
544        if iter != None:
545            store.remove(iter)
546            self.view.get_selection().select_path((0,))
547
548    def delete_boolean(self, args):
549        store, iter = self.boolean_treeview.get_selection().get_selected()
550        if iter != None:
551            store.remove(iter)
552            self.boolean_treeview.get_selection().select_path((0,))
553
554    def add_boolean(self, type):
555        self.boolean_name_entry.set_text("")
556        self.boolean_description_entry.set_text("")
557        rc = self.boolean_dialog.run()
558        self.boolean_dialog.hide()
559        if rc == Gtk.ResponseType.CANCEL:
560            return
561        iter = self.boolean_store.append()
562        self.boolean_store.set_value(iter, 0, self.boolean_name_entry.get_text())
563        self.boolean_store.set_value(iter, 1, self.boolean_description_entry.get_text())
564
565    def __add(self, type):
566        rc = self.file_dialog.run()
567        self.file_dialog.hide()
568        if rc == Gtk.ResponseType.CANCEL:
569            return
570        for i in self.file_dialog.get_filenames():
571            iter = self.store.append()
572            self.store.set_value(iter, 0, i)
573            self.store.set_value(iter, 1, type)
574
575    def exec_select(self, args):
576        self.file_dialog.set_select_multiple(0)
577        self.file_dialog.set_title(_("Select executable file to be confined."))
578        self.file_dialog.set_action(Gtk.FileChooserAction.OPEN)
579        self.file_dialog.set_current_folder("/usr/sbin")
580        rc = self.file_dialog.run()
581        self.file_dialog.hide()
582        if rc == Gtk.ResponseType.CANCEL:
583            return
584        self.exec_entry.set_text(self.file_dialog.get_filename())
585
586    def init_script_select(self, args):
587        self.file_dialog.set_select_multiple(0)
588        self.file_dialog.set_title(_("Select init script file to be confined."))
589        self.file_dialog.set_action(Gtk.FileChooserAction.OPEN)
590        self.file_dialog.set_current_folder("/etc/rc.d/init.d")
591        rc = self.file_dialog.run()
592        self.file_dialog.hide()
593        if rc == Gtk.ResponseType.CANCEL:
594            return
595        self.init_script_entry.set_text(self.file_dialog.get_filename())
596
597    def add(self, args):
598        self.file_dialog.set_title(_("Select file(s) that confined application creates or writes"))
599        self.file_dialog.set_current_folder("/")
600        self.file_dialog.set_action(Gtk.FileChooserAction.OPEN)
601        self.file_dialog.set_select_multiple(1)
602        self.__add(FILE)
603
604    def add_dir(self, args):
605        self.file_dialog.set_title(_("Select directory(s) that the confined application owns and writes into"))
606        self.file_dialog.set_current_folder("/")
607        self.file_dialog.set_select_multiple(1)
608        self.file_dialog.set_action(Gtk.FileChooserAction.SELECT_FOLDER)
609        self.__add(DIR)
610
611    def on_about_clicked(self, args):
612        dlg = xml.get_object("about_dialog")
613        dlg.run()
614        dlg.hide()
615
616    def quit(self, args):
617        Gtk.main_quit()
618
619    def setupScreen(self):
620        # Bring in widgets from glade file.
621        self.mainWindow = self.xml.get_object("main_window")
622        self.druid = self.xml.get_object("druid")
623        self.type = 0
624        self.name_entry = self.xml.get_object("name_entry")
625        self.name_entry.connect("insert_text", self.on_name_entry_changed)
626        self.name_entry.connect("focus_out_event", self.on_focus_out_event)
627        self.exec_entry = self.xml.get_object("exec_entry")
628        self.exec_button = self.xml.get_object("exec_button")
629        self.init_script_entry = self.xml.get_object("init_script_entry")
630        self.init_script_button = self.xml.get_object("init_script_button")
631        self.output_entry = self.xml.get_object("output_entry")
632        self.output_entry.set_text(os.getcwd())
633        self.xml.get_object("output_button").connect("clicked", self.output_button_clicked)
634
635        self.xwindows_user_radiobutton = self.xml.get_object("xwindows_user_radiobutton")
636        self.terminal_user_radiobutton = self.xml.get_object("terminal_user_radiobutton")
637        self.root_user_radiobutton = self.xml.get_object("root_user_radiobutton")
638        self.login_user_radiobutton = self.xml.get_object("login_user_radiobutton")
639        self.admin_user_radiobutton = self.xml.get_object("admin_user_radiobutton")
640        self.existing_user_radiobutton = self.xml.get_object("existing_user_radiobutton")
641
642        self.user_radiobutton = self.xml.get_object("user_radiobutton")
643        self.init_radiobutton = self.xml.get_object("init_radiobutton")
644        self.inetd_radiobutton = self.xml.get_object("inetd_radiobutton")
645        self.dbus_radiobutton = self.xml.get_object("dbus_radiobutton")
646        self.cgi_radiobutton = self.xml.get_object("cgi_radiobutton")
647        self.sandbox_radiobutton = self.xml.get_object("sandbox_radiobutton")
648        self.tmp_checkbutton = self.xml.get_object("tmp_checkbutton")
649        self.uid_checkbutton = self.xml.get_object("uid_checkbutton")
650        self.pam_checkbutton = self.xml.get_object("pam_checkbutton")
651        self.dbus_checkbutton = self.xml.get_object("dbus_checkbutton")
652        self.audit_checkbutton = self.xml.get_object("audit_checkbutton")
653        self.terminal_checkbutton = self.xml.get_object("terminal_checkbutton")
654        self.mail_checkbutton = self.xml.get_object("mail_checkbutton")
655        self.syslog_checkbutton = self.xml.get_object("syslog_checkbutton")
656        self.view = self.xml.get_object("write_treeview")
657        self.file_dialog = self.xml.get_object("filechooserdialog")
658
659        self.store = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_INT)
660        self.view.set_model(self.store)
661        col = Gtk.TreeViewColumn("", Gtk.CellRendererText(), text=0)
662        col.set_resizable(True)
663        self.view.append_column(col)
664        self.view.get_selection().select_path((0,))
665
666    def output_button_clicked(self, *args):
667        self.file_dialog.set_title(_("Select directory to generate policy files in"))
668        self.file_dialog.set_action(Gtk.FileChooserAction.SELECT_FOLDER)
669        self.file_dialog.set_select_multiple(0)
670        rc = self.file_dialog.run()
671        self.file_dialog.hide()
672        if rc == Gtk.ResponseType.CANCEL:
673            return
674        self.output_entry.set_text(self.file_dialog.get_filename())
675
676    def on_name_entry_changed(self, entry, text, size, position):
677        if text.find(" ") >= 0:
678            entry.stop_emission_by_name("insert-text")
679
680    def on_focus_out_event(self, entry, third):
681        name = entry.get_text()
682        if self.name != name:
683            if name in self.all_types:
684                if self.verify(_("Type %s_t already defined in current policy.\nDo you want to continue?") % name, _("Verify Name")) == Gtk.ResponseType.NO:
685                    entry.set_text("")
686                    return False
687            if name in self.all_modules:
688                if self.verify(_("Module %s already loaded in current policy.\nDo you want to continue?") % name, _("Verify Name")) == Gtk.ResponseType.NO:
689                    entry.set_text("")
690                    return False
691
692            file = "/etc/rc.d/init.d/" + name
693            if os.path.isfile(file) and self.init_script_entry.get_text() == "":
694                self.init_script_entry.set_text(file)
695
696            file = "/usr/sbin/" + name
697            if os.path.isfile(file) and self.exec_entry.get_text() == "":
698                self.exec_entry.set_text(file)
699
700        self.name = name
701        return False
702
703    def on_in_net_page_next(self, *args):
704        try:
705            sepolicy.generate.verify_ports(self.in_tcp_entry.get_text())
706            sepolicy.generate.verify_ports(self.in_udp_entry.get_text())
707        except ValueError as e:
708            self.error(e.message)
709            return True
710
711    def on_out_net_page_next(self, *args):
712        try:
713            sepolicy.generate.verify_ports(self.out_tcp_entry.get_text())
714            sepolicy.generate.verify_ports(self.out_udp_entry.get_text())
715        except ValueError as e:
716            self.error(e.message)
717            return True
718
719    def on_select_type_page_next(self, *args):
720        self.exec_entry.set_sensitive(self.confine_application())
721        self.exec_button.set_sensitive(self.confine_application())
722        self.init_script_entry.set_sensitive(self.init_radiobutton.get_active())
723        self.init_script_button.set_sensitive(self.init_radiobutton.get_active())
724
725    def on_existing_user_page_next(self, *args):
726        store, iter = self.view.get_selection().get_selected()
727        if iter != None:
728            self.error(_("You must select a user"))
729            return True
730
731    def on_name_page_next(self, *args):
732        name = self.name_entry.get_text()
733        if not name.isalnum():
734            self.error(_("You must add a name made up of letters and numbers and containing no spaces."))
735            return True
736
737        for i in self.label_dict:
738            text = '<b>%s</b>' % (self.label_dict[i] % ("'" + name + "'"))
739            i.set_markup(text)
740
741        for i in self.tooltip_dict:
742            text = self.tooltip_dict[i] % ("'" + name + "'")
743            i.set_tooltip_text(text)
744
745        if self.confine_application():
746            exe = self.exec_entry.get_text()
747            if exe == "":
748                self.error(_("You must enter a executable"))
749                return True
750            policy = sepolicy.generate.policy(name, self.get_type())
751            policy.set_program(exe)
752            policy.gen_writeable()
753            policy.gen_symbols()
754            for f in policy.files.keys():
755                iter = self.store.append()
756                self.store.set_value(iter, 0, f)
757                self.store.set_value(iter, 1, FILE)
758
759            for f in policy.dirs.keys():
760                iter = self.store.append()
761                self.store.set_value(iter, 0, f)
762                self.store.set_value(iter, 1, DIR)
763            self.tmp_checkbutton.set_active(policy.use_tmp)
764            self.uid_checkbutton.set_active(policy.use_uid)
765            self.pam_checkbutton.set_active(policy.use_pam)
766            self.dbus_checkbutton.set_active(policy.use_dbus)
767            self.audit_checkbutton.set_active(policy.use_audit)
768            self.terminal_checkbutton.set_active(policy.use_terminal)
769            self.mail_checkbutton.set_active(policy.use_mail)
770            self.syslog_checkbutton.set_active(policy.use_syslog)
771
772    def stand_alone(self):
773        desktopName = _("Configure SELinux")
774
775        self.setupScreen()
776        self.mainWindow.connect("destroy", self.quit)
777
778        self.mainWindow.show_all()
779        Gtk.main()
780
781if __name__ == "__main__":
782    signal.signal(signal.SIGINT, signal.SIG_DFL)
783
784    app = childWindow()
785    app.stand_alone()
786