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 = "selinux-gui" 42try: 43 import gettext 44 kwargs = {} 45 if sys.version_info < (3,): 46 kwargs['unicode'] = True 47 t = gettext.translation(PROGNAME, 48 localedir="/usr/share/locale", 49 **kwargs, 50 fallback=True) 51 _ = t.gettext 52except: 53 try: 54 import builtins 55 builtins.__dict__['_'] = str 56 except ImportError: 57 import __builtin__ 58 __builtin__.__dict__['_'] = unicode 59 60 61class Modifier: 62 63 def __init__(self, name, on, save): 64 self.on = on 65 self.name = name 66 self.save = save 67 68 def set(self, value): 69 self.on = value 70 self.save = True 71 72 def isOn(self): 73 return self.on 74 75 76class Boolean(Modifier): 77 78 def __init__(self, name, val, save=False): 79 Modifier.__init__(self, name, val, save) 80 81ACTIVE = 0 82MODULE = 1 83DESC = 2 84BOOLEAN = 3 85 86 87class booleansPage: 88 89 def __init__(self, xml, doDebug=None): 90 self.xml = xml 91 self.window = self.xml.get_object("mainWindow").get_root_window() 92 self.local = False 93 self.types = [] 94 self.selinuxsupport = True 95 self.typechanged = False 96 self.doDebug = doDebug 97 self.busy_cursor = Gdk.Cursor.new(Gdk.CursorType.WATCH) 98 self.ready_cursor = Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR) 99 100 # Bring in widgets from glade file. 101 self.booleansFilter = xml.get_object("booleansFilter") 102 self.booleansFilter.connect("focus_out_event", self.filter_changed) 103 self.booleansFilter.connect("activate", self.filter_changed) 104 self.booleansFilter.connect("changed", self.filter_changed) 105 106 self.booleansView = xml.get_object("booleansView") 107 108 self.revertButton = xml.get_object("booleanRevertButton") 109 self.revertButton.set_sensitive(self.local) 110 self.revertButton.connect("clicked", self.on_revert_clicked) 111 listStore = Gtk.ListStore(GObject.TYPE_STRING) 112 cell = Gtk.CellRendererText() 113 114 self.store = Gtk.ListStore(GObject.TYPE_BOOLEAN, GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING) 115 self.store.set_sort_column_id(1, Gtk.SortType.ASCENDING) 116 self.booleansView.set_model(self.store) 117 118 checkbox = Gtk.CellRendererToggle() 119 checkbox.connect("toggled", self.boolean_toggled) 120 col = Gtk.TreeViewColumn('Active', checkbox, active=ACTIVE) 121 col.set_clickable(True) 122 col.set_sort_column_id(ACTIVE) 123 self.booleansView.append_column(col) 124 125 col = Gtk.TreeViewColumn("Module", Gtk.CellRendererText(), text=MODULE) 126 col.set_sort_column_id(MODULE) 127 col.set_resizable(True) 128 self.booleansView.append_column(col) 129 130 col = Gtk.TreeViewColumn("Description", Gtk.CellRendererText(), text=DESC) 131 col.set_sizing(Gtk.TreeViewColumnSizing.FIXED) 132 col.set_fixed_width(400) 133 col.set_sort_column_id(DESC) 134 col.set_resizable(True) 135 self.booleansView.append_column(col) 136 137 col = Gtk.TreeViewColumn("Name", Gtk.CellRendererText(), text=BOOLEAN) 138 col.set_sort_column_id(BOOLEAN) 139 col.set_resizable(True) 140 self.booleansView.set_search_equal_func(self.__search) 141 self.booleansView.append_column(col) 142 self.filter = "" 143 self.load(self.filter) 144 145 def error(self, message): 146 dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.ERROR, 147 Gtk.ButtonsType.CLOSE, 148 message) 149 dlg.set_position(Gtk.WindowPosition.MOUSE) 150 dlg.show_all() 151 dlg.run() 152 dlg.destroy() 153 154 def __search(self, model, col, key, i): 155 sort_col = self.store.get_sort_column_id()[0] 156 if sort_col > 0: 157 val = model.get_value(i, sort_col) 158 if val.lower().startswith(key.lower()): 159 return False 160 return True 161 162 def wait(self): 163 self.window.set_cursor(self.busy_cursor) 164 semanagePage.idle_func() 165 166 def ready(self): 167 self.window.set_cursor(self.ready_cursor) 168 semanagePage.idle_func() 169 170 def deleteDialog(self): 171 store, iter = self.booleansView.get_selection().get_selected() 172 if iter is None: 173 return 174 boolean = store.get_value(iter, BOOLEAN) 175 # change cursor 176 if boolean is None: 177 return 178 try: 179 self.wait() 180 (rc, out) = getstatusoutput("semanage boolean -d %s" % boolean) 181 182 self.ready() 183 if rc != 0: 184 return self.error(out) 185 self.load(self.filter) 186 except ValueError as e: 187 self.error(e.args[0]) 188 189 def filter_changed(self, *arg): 190 filter = arg[0].get_text() 191 if filter != self.filter: 192 self.load(filter) 193 self.filter = filter 194 195 def use_menus(self): 196 return False 197 198 def get_description(self): 199 return _("Boolean") 200 201 def match(self, key, filter=""): 202 try: 203 f = filter.lower() 204 cat = self.booleans.get_category(key).lower() 205 val = self.booleans.get_desc(key).lower() 206 k = key.lower() 207 return val.find(f) >= 0 or k.find(f) >= 0 or cat.find(f) >= 0 208 except: 209 return False 210 211 def load(self, filter=None): 212 self.store.clear() 213 self.booleans = seobject.booleanRecords() 214 booleansList = self.booleans.get_all(self.local) 215 for name in booleansList: 216 rec = booleansList[name] 217 if self.match(name, filter): 218 iter = self.store.append() 219 self.store.set_value(iter, ACTIVE, rec[2] == 1) 220 self.store.set_value(iter, MODULE, self.booleans.get_category(name)) 221 self.store.set_value(iter, DESC, self.booleans.get_desc(name)) 222 self.store.set_value(iter, BOOLEAN, name) 223 224 def boolean_toggled(self, widget, row): 225 iter = self.store.get_iter(row) 226 val = self.store.get_value(iter, ACTIVE) 227 key = self.store.get_value(iter, BOOLEAN) 228 self.store.set_value(iter, ACTIVE, not val) 229 self.wait() 230 setsebool = "/usr/sbin/setsebool -P %s %d" % (key, not val) 231 rc, out = getstatusoutput(setsebool) 232 if rc != 0: 233 self.error(out) 234 self.load(self.filter) 235 self.ready() 236 237 def on_revert_clicked(self, button): 238 self.wait() 239 setsebool = "semanage boolean --deleteall" 240 getstatusoutput(setsebool) 241 self.load(self.filter) 242 self.ready() 243 244 def on_local_clicked(self, button): 245 self.local = not self.local 246 self.revertButton.set_sensitive(self.local) 247 248 if self.local: 249 button.set_label(_("all")) 250 else: 251 button.set_label(_("Customized")) 252 253 self.load(self.filter) 254 return True 255