1#
2# booleansPage.py - GUI for Booleans page in system-config-securitylevel
3#
4# Dan Walsh <dwalsh@redhat.com>
5#
6# Copyright 2006, 2007 Red Hat, Inc.
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20#
21import sys
22from gi.repository import Gdk, GObject, Gtk
23import seobject
24import semanagePage
25
26INSTALLPATH = '/usr/share/system-config-selinux'
27sys.path.append(INSTALLPATH)
28
29try:
30    from subprocess import getstatusoutput
31except ImportError:
32    from commands import getstatusoutput
33
34ENFORCING = 0
35PERMISSIVE = 1
36DISABLED = 2
37
38##
39## I18N
40##
41PROGNAME = "policycoreutils"
42try:
43    import gettext
44    kwargs = {}
45    if sys.version_info < (3,):
46        kwargs['unicode'] = True
47    gettext.install(PROGNAME,
48                    localedir="/usr/share/locale",
49                    codeset='utf-8',
50                    **kwargs)
51except:
52    try:
53        import builtins
54        builtins.__dict__['_'] = str
55    except ImportError:
56        import __builtin__
57        __builtin__.__dict__['_'] = unicode
58
59
60class Modifier:
61
62    def __init__(self, name, on, save):
63        self.on = on
64        self.name = name
65        self.save = save
66
67    def set(self, value):
68        self.on = value
69        self.save = True
70
71    def isOn(self):
72        return self.on
73
74
75class Boolean(Modifier):
76
77    def __init__(self, name, val, save=False):
78        Modifier.__init__(self, name, val, save)
79
80ACTIVE = 0
81MODULE = 1
82DESC = 2
83BOOLEAN = 3
84
85
86class booleansPage:
87
88    def __init__(self, xml, doDebug=None):
89        self.xml = xml
90        self.window = self.xml.get_object("mainWindow").get_root_window()
91        self.local = False
92        self.types = []
93        self.selinuxsupport = True
94        self.typechanged = False
95        self.doDebug = doDebug
96        self.busy_cursor = Gdk.Cursor.new(Gdk.CursorType.WATCH)
97        self.ready_cursor = Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR)
98
99        # Bring in widgets from glade file.
100        self.booleansFilter = xml.get_object("booleansFilter")
101        self.booleansFilter.connect("focus_out_event", self.filter_changed)
102        self.booleansFilter.connect("activate", self.filter_changed)
103        self.booleansFilter.connect("changed", self.filter_changed)
104
105        self.booleansView = xml.get_object("booleansView")
106
107        self.revertButton = xml.get_object("booleanRevertButton")
108        self.revertButton.set_sensitive(self.local)
109        self.revertButton.connect("clicked", self.on_revert_clicked)
110        listStore = Gtk.ListStore(GObject.TYPE_STRING)
111        cell = Gtk.CellRendererText()
112
113        self.store = Gtk.ListStore(GObject.TYPE_BOOLEAN, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING)
114        self.store.set_sort_column_id(1, Gtk.SortType.ASCENDING)
115        self.booleansView.set_model(self.store)
116
117        checkbox = Gtk.CellRendererToggle()
118        checkbox.connect("toggled", self.boolean_toggled)
119        col = Gtk.TreeViewColumn('Active', checkbox, active=ACTIVE)
120        col.set_clickable(True)
121        col.set_sort_column_id(ACTIVE)
122        self.booleansView.append_column(col)
123
124        col = Gtk.TreeViewColumn("Module", Gtk.CellRendererText(), text=MODULE)
125        col.set_sort_column_id(MODULE)
126        col.set_resizable(True)
127        self.booleansView.append_column(col)
128
129        col = Gtk.TreeViewColumn("Description", Gtk.CellRendererText(), text=DESC)
130        col.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
131        col.set_fixed_width(400)
132        col.set_sort_column_id(DESC)
133        col.set_resizable(True)
134        self.booleansView.append_column(col)
135
136        col = Gtk.TreeViewColumn("Name", Gtk.CellRendererText(), text=BOOLEAN)
137        col.set_sort_column_id(BOOLEAN)
138        col.set_resizable(True)
139        self.booleansView.set_search_equal_func(self.__search)
140        self.booleansView.append_column(col)
141        self.filter = ""
142        self.load(self.filter)
143
144    def error(self, message):
145        dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.ERROR,
146                                Gtk.ButtonsType.CLOSE,
147                                message)
148        dlg.set_position(Gtk.WindowPosition.MOUSE)
149        dlg.show_all()
150        dlg.run()
151        dlg.destroy()
152
153    def __search(self, model, col, key, i):
154        sort_col = self.store.get_sort_column_id()[0]
155        if sort_col > 0:
156            val = model.get_value(i, sort_col)
157            if val.lower().startswith(key.lower()):
158                return False
159        return True
160
161    def wait(self):
162        self.window.set_cursor(self.busy_cursor)
163        semanagePage.idle_func()
164
165    def ready(self):
166        self.window.set_cursor(self.ready_cursor)
167        semanagePage.idle_func()
168
169    def deleteDialog(self):
170        store, iter = self.booleansView.get_selection().get_selected()
171        if iter is None:
172            return
173        boolean = store.get_value(iter, BOOLEAN)
174        # change cursor
175        if boolean is None:
176            return
177        try:
178            self.wait()
179            (rc, out) = getstatusoutput("semanage boolean -d %s" % boolean)
180
181            self.ready()
182            if rc != 0:
183                return self.error(out)
184            self.load(self.filter)
185        except ValueError as e:
186            self.error(e.args[0])
187
188    def filter_changed(self, *arg):
189        filter = arg[0].get_text()
190        if filter != self.filter:
191            self.load(filter)
192            self.filter = filter
193
194    def use_menus(self):
195        return False
196
197    def get_description(self):
198        return _("Boolean")
199
200    def match(self, key, filter=""):
201        try:
202            f = filter.lower()
203            cat = self.booleans.get_category(key).lower()
204            val = self.booleans.get_desc(key).lower()
205            k = key.lower()
206            return val.find(f) >= 0 or k.find(f) >= 0 or cat.find(f) >= 0
207        except:
208            return False
209
210    def load(self, filter=None):
211        self.store.clear()
212        self.booleans = seobject.booleanRecords()
213        booleansList = self.booleans.get_all(self.local)
214        for name in booleansList:
215            rec = booleansList[name]
216            if self.match(name, filter):
217                iter = self.store.append()
218                self.store.set_value(iter, ACTIVE, rec[2] == 1)
219                self.store.set_value(iter, MODULE, self.booleans.get_category(name))
220                self.store.set_value(iter, DESC, self.booleans.get_desc(name))
221                self.store.set_value(iter, BOOLEAN, name)
222
223    def boolean_toggled(self, widget, row):
224        iter = self.store.get_iter(row)
225        val = self.store.get_value(iter, ACTIVE)
226        key = self.store.get_value(iter, BOOLEAN)
227        self.store.set_value(iter, ACTIVE, not val)
228        self.wait()
229        setsebool = "/usr/sbin/setsebool -P %s %d" % (key, not val)
230        rc, out = getstatusoutput(setsebool)
231        if rc != 0:
232            self.error(out)
233        self.load(self.filter)
234        self.ready()
235
236    def on_revert_clicked(self, button):
237        self.wait()
238        setsebool = "semanage boolean --deleteall"
239        getstatusoutput(setsebool)
240        self.load(self.filter)
241        self.ready()
242
243    def on_local_clicked(self, button):
244        self.local = not self.local
245        self.revertButton.set_sensitive(self.local)
246
247        if self.local:
248            button.set_label(_("all"))
249        else:
250            button.set_label(_("Customized"))
251
252        self.load(self.filter)
253        return True
254