0f3beeb00e
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>
210 lines
7.6 KiB
Python
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()]
|