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