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