1# statusPage.py - show selinux status 2## Copyright (C) 2006-2009 Red Hat, Inc. 3 4## This program is free software; you can redistribute it and/or modify 5## it under the terms of the GNU General Public License as published by 6## the Free Software Foundation; either version 2 of the License, or 7## (at your option) any later version. 8 9## This program is distributed in the hope that it will be useful, 10## but WITHOUT ANY WARRANTY; without even the implied warranty of 11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12## GNU General Public License for more details. 13 14## You should have received a copy of the GNU General Public License 15## along with this program; if not, write to the Free Software 16## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 18## Author: Dan Walsh 19import os 20import sys 21from gi.repository import Gtk 22import selinux 23 24INSTALLPATH = '/usr/share/system-config-selinux' 25sys.path.append(INSTALLPATH) 26 27ENFORCING = 1 28PERMISSIVE = 0 29DISABLED = -1 30modearray = ("disabled", "permissive", "enforcing") 31 32SELINUXDIR = "/etc/selinux/" 33RELABELFILE = "/.autorelabel" 34 35## 36## I18N 37## 38PROGNAME = "selinux-gui" 39try: 40 import gettext 41 kwargs = {} 42 if sys.version_info < (3,): 43 kwargs['unicode'] = True 44 t = gettext.translation(PROGNAME, 45 localedir="/usr/share/locale", 46 **kwargs, 47 fallback=True) 48 _ = t.gettext 49except: 50 try: 51 import builtins 52 builtins.__dict__['_'] = str 53 except ImportError: 54 import __builtin__ 55 __builtin__.__dict__['_'] = unicode 56 57 58class statusPage: 59 60 def __init__(self, xml): 61 self.xml = xml 62 self.needRelabel = False 63 64 self.type = selinux.selinux_getpolicytype() 65 # Bring in widgets from glade file. 66 self.selinuxTypeOptionMenu = xml.get_object("selinuxTypeOptionMenu") 67 self.typeLabel = xml.get_object("typeLabel") 68 self.enabledOptionMenu = xml.get_object("enabledOptionMenu") 69 self.currentOptionMenu = xml.get_object("currentOptionMenu") 70 self.relabel_checkbutton = xml.get_object("relabelCheckbutton") 71 self.relabel_checkbutton.set_active(self.is_relabel()) 72 self.relabel_checkbutton.connect("toggled", self.on_relabel_toggle) 73 if self.get_current_mode() == ENFORCING or self.get_current_mode() == PERMISSIVE: 74 self.currentOptionMenu.append_text(_("Permissive")) 75 self.currentOptionMenu.append_text(_("Enforcing")) 76 self.currentOptionMenu.set_active(self.get_current_mode()) 77 self.currentOptionMenu.connect("changed", self.set_current_mode) 78 self.currentOptionMenu.set_sensitive(True) 79 else: 80 self.currentOptionMenu.append_text(_("Disabled")) 81 self.currentOptionMenu.set_active(0) 82 self.currentOptionMenu.set_sensitive(False) 83 84 if self.read_selinux_config() is None: 85 self.selinuxsupport = False 86 else: 87 self.enabledOptionMenu.connect("changed", self.enabled_changed) 88 # 89 # This line must come after read_selinux_config 90 # 91 self.selinuxTypeOptionMenu.connect("changed", self.typemenu_changed) 92 93 self.typeLabel.set_mnemonic_widget(self.selinuxTypeOptionMenu) 94 95 def use_menus(self): 96 return False 97 98 def get_description(self): 99 return _("Status") 100 101 def get_current_mode(self): 102 if selinux.is_selinux_enabled(): 103 if selinux.security_getenforce() > 0: 104 return ENFORCING 105 else: 106 return PERMISSIVE 107 else: 108 return DISABLED 109 110 def set_current_mode(self, menu): 111 selinux.security_setenforce(menu.get_active() == 1) 112 113 def is_relabel(self): 114 return os.access(RELABELFILE, os.F_OK) != 0 115 116 def on_relabel_toggle(self, button): 117 if button.get_active(): 118 fd = open(RELABELFILE, "w") 119 fd.close() 120 else: 121 if os.access(RELABELFILE, os.F_OK) != 0: 122 os.unlink(RELABELFILE) 123 124 def verify(self, message): 125 dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO, 126 Gtk.ButtonsType.YES_NO, 127 message) 128 dlg.set_position(Gtk.WindowPosition.MOUSE) 129 dlg.show_all() 130 rc = dlg.run() 131 dlg.destroy() 132 return rc 133 134 def typemenu_changed(self, menu): 135 type = self.get_type() 136 enabled = self.enabledOptionMenu.get_active() 137 if self.initialtype != type: 138 if self.verify(_("Changing the policy type will cause a relabel of the entire file system on the next boot. Relabeling takes a long time depending on the size of the file system. Do you wish to continue?")) == Gtk.ResponseType.NO: 139 menu.set_active(self.typeHistory) 140 return None 141 142 self.relabel_checkbutton.set_active(True) 143 144 self.write_selinux_config(modearray[enabled], type) 145 self.typeHistory = menu.get_active() 146 147 def enabled_changed(self, combo): 148 enabled = combo.get_active() 149 type = self.get_type() 150 151 if self.initEnabled != DISABLED and enabled == DISABLED: 152 if self.verify(_("Changing to SELinux disabled requires a reboot. It is not recommended. If you later decide to turn SELinux back on, the system will be required to relabel. If you just want to see if SELinux is causing a problem on your system, you can go to permissive mode which will only log errors and not enforce SELinux policy. Permissive mode does not require a reboot Do you wish to continue?")) == Gtk.ResponseType.NO: 153 combo.set_active(self.enabled) 154 return None 155 156 if self.initEnabled == DISABLED and enabled < 2: 157 if self.verify(_("Changing to SELinux enabled will cause a relabel of the entire file system on the next boot. Relabeling takes a long time depending on the size of the file system. Do you wish to continue?")) == Gtk.ResponseType.NO: 158 combo.set_active(self.enabled) 159 return None 160 self.relabel_checkbutton.set_active(True) 161 162 self.write_selinux_config(modearray[enabled], type) 163 self.enabled = enabled 164 165 def write_selinux_config(self, enforcing, type): 166 path = selinux.selinux_path() + "config" 167 backup_path = path + ".bck" 168 fd = open(path) 169 lines = fd.readlines() 170 fd.close() 171 fd = open(backup_path, "w") 172 for l in lines: 173 if l.startswith("SELINUX="): 174 fd.write("SELINUX=%s\n" % enforcing) 175 continue 176 if l.startswith("SELINUXTYPE="): 177 fd.write("SELINUXTYPE=%s\n" % type) 178 continue 179 fd.write(l) 180 fd.close() 181 os.rename(backup_path, path) 182 183 def read_selinux_config(self): 184 self.initialtype = selinux.selinux_getpolicytype()[1] 185 try: 186 self.initEnabled = selinux.selinux_getenforcemode()[1] 187 except: 188 self.initEnabled = False 189 pass 190 self.enabled = self.initEnabled 191 self.enabledOptionMenu.set_active(self.enabled + 1) 192 193 self.types = [] 194 195 n = 0 196 current = n 197 198 for i in os.listdir(SELINUXDIR): 199 if os.path.isdir(SELINUXDIR + i) and os.path.isdir(SELINUXDIR + i + "/policy"): 200 self.types.append(i) 201 self.selinuxTypeOptionMenu.append_text(i) 202 if i == self.initialtype: 203 current = n 204 n = n + 1 205 self.selinuxTypeOptionMenu.set_active(current) 206 self.typeHistory = current 207 208 return 0 209 210 def get_type(self): 211 return self.types[self.selinuxTypeOptionMenu.get_active()] 212