platform_external_selinux/gui/statusPage.py
Nicolas Iooss 0f3beeb00e gui: port to Python 3 by migrating to PyGI
PyGTK has been deprecated in favor of PyGI+GTK and thus has never been
ported to python3. Using pygi-convert.sh from
https://git.gnome.org/browse/pygobject/tree/pygi-convert.sh helps
migrating most of the API but gnome-python.

The glade file has been converted to GtkBuilder using

  gtk-builder-convert system-config-selinux.glade system-config-selinux.ui

and some fixes in order to provide an application window (object
GnomeApp disappeared, GtkVBox is deprecated, etc.). The associated
Python code also needed some modifications in order to migrate to
GtkBuilder.

The result has been tested on Arch Linux with Python 3.6. There are some
bugs in the GUI itself, for which patches will be sent afterwards.

Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
2017-09-25 12:54:12 -04:00

210 lines
7.6 KiB
Python

# statusPage.py - show selinux status
## Copyright (C) 2006-2009 Red Hat, Inc.
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
## Author: Dan Walsh
import os
import sys
from gi.repository import Gtk
import selinux
INSTALLPATH = '/usr/share/system-config-selinux'
sys.path.append(INSTALLPATH)
ENFORCING = 1
PERMISSIVE = 0
DISABLED = -1
modearray = ("disabled", "permissive", "enforcing")
SELINUXDIR = "/etc/selinux/"
RELABELFILE = "/.autorelabel"
##
## I18N
##
PROGNAME = "policycoreutils"
try:
import gettext
kwargs = {}
if sys.version_info < (3,):
kwargs['unicode'] = True
gettext.install(PROGNAME,
localedir="/usr/share/locale",
codeset='utf-8',
**kwargs)
except:
try:
import builtins
builtins.__dict__['_'] = str
except ImportError:
import __builtin__
__builtin__.__dict__['_'] = unicode
class statusPage:
def __init__(self, xml):
self.xml = xml
self.needRelabel = False
self.type = selinux.selinux_getpolicytype()
# Bring in widgets from glade file.
self.selinuxTypeOptionMenu = xml.get_object("selinuxTypeOptionMenu")
self.typeLabel = xml.get_object("typeLabel")
self.enabledOptionMenu = xml.get_object("enabledOptionMenu")
self.currentOptionMenu = xml.get_object("currentOptionMenu")
self.relabel_checkbutton = xml.get_object("relabelCheckbutton")
self.relabel_checkbutton.set_active(self.is_relabel())
self.relabel_checkbutton.connect("toggled", self.on_relabel_toggle)
if self.get_current_mode() == ENFORCING or self.get_current_mode() == PERMISSIVE:
self.currentOptionMenu.append_text(_("Permissive"))
self.currentOptionMenu.append_text(_("Enforcing"))
self.currentOptionMenu.set_active(self.get_current_mode())
self.currentOptionMenu.connect("changed", self.set_current_mode)
self.currentOptionMenu.set_sensitive(True)
else:
self.currentOptionMenu.append_text(_("Disabled"))
self.currentOptionMenu.set_active(0)
self.currentOptionMenu.set_sensitive(False)
if self.read_selinux_config() is None:
self.selinuxsupport = False
else:
self.enabledOptionMenu.connect("changed", self.enabled_changed)
#
# This line must come after read_selinux_config
#
self.selinuxTypeOptionMenu.connect("changed", self.typemenu_changed)
self.typeLabel.set_mnemonic_widget(self.selinuxTypeOptionMenu)
def use_menus(self):
return False
def get_description(self):
return _("Status")
def get_current_mode(self):
if selinux.is_selinux_enabled():
if selinux.security_getenforce() > 0:
return ENFORCING
else:
return PERMISSIVE
else:
return DISABLED
def set_current_mode(self, menu):
selinux.security_setenforce(menu.get_active() == 1)
def is_relabel(self):
return os.access(RELABELFILE, os.F_OK) != 0
def on_relabel_toggle(self, button):
if button.get_active():
fd = open(RELABELFILE, "w")
fd.close()
else:
if os.access(RELABELFILE, os.F_OK) != 0:
os.unlink(RELABELFILE)
def verify(self, message):
dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO,
Gtk.ButtonsType.YES_NO,
message)
dlg.set_position(Gtk.WindowPosition.MOUSE)
dlg.show_all()
rc = dlg.run()
dlg.destroy()
return rc
def typemenu_changed(self, menu):
type = self.get_type()
enabled = self.enabledOptionMenu.get_active()
if self.initialtype != type:
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:
menu.set_active(self.typeHistory)
return None
self.relabel_checkbutton.set_active(True)
self.write_selinux_config(modearray[enabled], type)
self.typeHistory = menu.get_active()
def enabled_changed(self, combo):
enabled = combo.get_active()
type = self.get_type()
if self.initEnabled != DISABLED and enabled == DISABLED:
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:
combo.set_active(self.enabled)
return None
if self.initEnabled == DISABLED and enabled < 2:
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:
combo.set_active(self.enabled)
return None
self.relabel_checkbutton.set_active(True)
self.write_selinux_config(modearray[enabled], type)
self.enabled = enabled
def write_selinux_config(self, enforcing, type):
path = selinux.selinux_path() + "config"
backup_path = path + ".bck"
fd = open(path)
lines = fd.readlines()
fd.close()
fd = open(backup_path, "w")
for l in lines:
if l.startswith("SELINUX="):
fd.write("SELINUX=%s\n" % enforcing)
continue
if l.startswith("SELINUXTYPE="):
fd.write("SELINUXTYPE=%s\n" % type)
continue
fd.write(l)
fd.close()
os.rename(backup_path, path)
def read_selinux_config(self):
self.initialtype = selinux.selinux_getpolicytype()[1]
try:
self.initEnabled = selinux.selinux_getenforcemode()[1]
except:
self.initEnabled = False
pass
self.enabled = self.initEnabled
self.enabledOptionMenu.set_active(self.enabled + 1)
self.types = []
n = 0
current = n
for i in os.listdir(SELINUXDIR):
if os.path.isdir(SELINUXDIR + i) and os.path.isdir(SELINUXDIR + i + "/policy"):
self.types.append(i)
self.selinuxTypeOptionMenu.append_text(i)
if i == self.initialtype:
current = n
n = n + 1
self.selinuxTypeOptionMenu.set_active(current)
self.typeHistory = current
return 0
def get_type(self):
return self.types[self.selinuxTypeOptionMenu.get_active()]