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 import selinux
     27 
     28 INSTALLPATH = '/usr/share/system-config-selinux'
     29 sys.path.append(INSTALLPATH)
     30 
     31 try:
     32     from subprocess import getstatusoutput
     33 except ImportError:
     34     from commands import getstatusoutput
     35 
     36 ENFORCING = 1
     37 PERMISSIVE = 0
     38 DISABLED = -1
     39 modearray = ("disabled", "permissive", "enforcing")
     40 
     41 SELINUXDIR = "/etc/selinux/"
     42 RELABELFILE = "/.autorelabel"
     43 
     44 ##
     45 ## I18N
     46 ##
     47 PROGNAME = "policycoreutils"
     48 try:
     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)
     57 except:
     58     try:
     59         import builtins
     60         builtins.__dict__['_'] = str
     61     except ImportError:
     62         import __builtin__
     63         __builtin__.__dict__['_'] = unicode
     64 
     65 
     66 class 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