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