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