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