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 string 20import gtk 21import gtk.glade 22import os 23import gobject 24import sys 25import tempfile 26import selinux 27 28INSTALLPATH = '/usr/share/system-config-selinux' 29sys.path.append(INSTALLPATH) 30 31try: 32 from subprocess import getstatusoutput 33except ImportError: 34 from commands import getstatusoutput 35 36ENFORCING = 1 37PERMISSIVE = 0 38DISABLED = -1 39modearray = ("disabled", "permissive", "enforcing") 40 41SELINUXDIR = "/etc/selinux/" 42RELABELFILE = "/.autorelabel" 43 44## 45## I18N 46## 47PROGNAME = "policycoreutils" 48try: 49 import gettext 50 kwargs = {} 51 if sys.version_info < (3,): 52 kwargs['unicode'] = True 53 gettext.install(PROGNAME, 54 localedir="/usr/share/locale", 55 codeset='utf-8', 56 **kwargs) 57except: 58 try: 59 import builtins 60 builtins.__dict__['_'] = str 61 except ImportError: 62 import __builtin__ 63 __builtin__.__dict__['_'] = unicode 64 65 66class statusPage: 67 68 def __init__(self, xml): 69 self.xml = xml 70 self.needRelabel = False 71 72 self.type = selinux.selinux_getpolicytype() 73 # Bring in widgets from glade file. 74 self.typeHBox = xml.get_widget("typeHBox") 75 self.selinuxTypeOptionMenu = xml.get_widget("selinuxTypeOptionMenu") 76 self.typeLabel = xml.get_widget("typeLabel") 77 self.enabledOptionMenu = xml.get_widget("enabledOptionMenu") 78 self.currentOptionMenu = xml.get_widget("currentOptionMenu") 79 self.relabel_checkbutton = xml.get_widget("relabelCheckbutton") 80 self.relabel_checkbutton.set_active(self.is_relabel()) 81 self.relabel_checkbutton.connect("toggled", self.on_relabel_toggle) 82 if self.get_current_mode() == ENFORCING or self.get_current_mode() == PERMISSIVE: 83 self.currentOptionMenu.append_text(_("Permissive")) 84 self.currentOptionMenu.append_text(_("Enforcing")) 85 self.currentOptionMenu.set_active(self.get_current_mode()) 86 self.currentOptionMenu.connect("changed", self.set_current_mode) 87 self.currentOptionMenu.set_sensitive(True) 88 else: 89 self.currentOptionMenu.append_text(_("Disabled")) 90 self.currentOptionMenu.set_active(0) 91 self.currentOptionMenu.set_sensitive(False) 92 93 if self.read_selinux_config() == None: 94 self.selinuxsupport = False 95 else: 96 self.enabledOptionMenu.connect("changed", self.enabled_changed) 97 # 98 # This line must come after read_selinux_config 99 # 100 self.selinuxTypeOptionMenu.connect("changed", self.typemenu_changed) 101 102 self.typeLabel.set_mnemonic_widget(self.selinuxTypeOptionMenu) 103 104 def use_menus(self): 105 return False 106 107 def get_description(self): 108 return _("Status") 109 110 def get_current_mode(self): 111 if selinux.is_selinux_enabled(): 112 if selinux.security_getenforce() > 0: 113 return ENFORCING 114 else: 115 return PERMISSIVE 116 else: 117 return DISABLED 118 119 def set_current_mode(self, menu): 120 selinux.security_setenforce(menu.get_active() == 1) 121 122 def is_relabel(self): 123 return os.access(RELABELFILE, os.F_OK) != 0 124 125 def on_relabel_toggle(self, button): 126 if button.get_active(): 127 fd = open(RELABELFILE, "w") 128 fd.close() 129 else: 130 if os.access(RELABELFILE, os.F_OK) != 0: 131 os.unlink(RELABELFILE) 132 133 def verify(self, message): 134 dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO, 135 gtk.BUTTONS_YES_NO, 136 message) 137 dlg.set_position(gtk.WIN_POS_MOUSE) 138 dlg.show_all() 139 rc = dlg.run() 140 dlg.destroy() 141 return rc 142 143 def typemenu_changed(self, menu): 144 type = self.get_type() 145 enabled = self.enabledOptionMenu.get_active() 146 if self.initialtype != type: 147 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.RESPONSE_NO: 148 menu.set_active(self.typeHistory) 149 return None 150 151 self.relabel_checkbutton.set_active(True) 152 153 self.write_selinux_config(modearray[enabled], type) 154 self.typeHistory = menu.get_active() 155 156 def enabled_changed(self, combo): 157 enabled = combo.get_active() 158 type = self.get_type() 159 160 if self.initEnabled != DISABLED and enabled == DISABLED: 161 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.RESPONSE_NO: 162 combo.set_active(self.enabled) 163 return None 164 165 if self.initEnabled == DISABLED and enabled < 2: 166 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.RESPONSE_NO: 167 combo.set_active(self.enabled) 168 return None 169 self.relabel_checkbutton.set_active(True) 170 171 self.write_selinux_config(modearray[enabled], type) 172 self.enabled = enabled 173 174 def write_selinux_config(self, enforcing, type): 175 path = selinux.selinux_path() + "config" 176 backup_path = path + ".bck" 177 fd = open(path) 178 lines = fd.readlines() 179 fd.close() 180 fd = open(backup_path, "w") 181 for l in lines: 182 if l.startswith("SELINUX="): 183 fd.write("SELINUX=%s\n" % enforcing) 184 continue 185 if l.startswith("SELINUXTYPE="): 186 fd.write("SELINUXTYPE=%s\n" % type) 187 continue 188 fd.write(l) 189 fd.close() 190 os.rename(backup_path, path) 191 192 def read_selinux_config(self): 193 self.initialtype = selinux.selinux_getpolicytype()[1] 194 try: 195 self.initEnabled = selinux.selinux_getenforcemode()[1] 196 except: 197 self.initEnabled = False 198 pass 199 self.enabled = self.initEnabled 200 self.enabledOptionMenu.set_active(self.enabled + 1) 201 202 self.types = [] 203 204 n = 0 205 current = n 206 207 for i in os.listdir(SELINUXDIR): 208 if os.path.isdir(SELINUXDIR + i) and os.path.isdir(SELINUXDIR + i + "/policy"): 209 self.types.append(i) 210 self.selinuxTypeOptionMenu.append_text(i) 211 if i == self.initialtype: 212 current = n 213 n = n + 1 214 self.selinuxTypeOptionMenu.set_active(current) 215 self.typeHistory = current 216 217 return 0 218 219 def get_type(self): 220 return self.types[self.selinuxTypeOptionMenu.get_active()] 221