# 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 string
import gtk
import gtk.glade
import os
import gobject
import sys
import tempfile

INSTALLPATH = '/usr/share/system-config-selinux'
sys.path.append(INSTALLPATH)

import commands
ENFORCING = 1
PERMISSIVE = 0
DISABLED = -1
modearray = ("disabled", "permissive", "enforcing")

SELINUXDIR = "/etc/selinux/"
RELABELFILE = "/.autorelabel"

##
## I18N
##
PROGNAME = "policycoreutils"
import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
gettext.textdomain(PROGNAME)
import selinux
try:
    gettext.install(PROGNAME, localedir="/usr/share/locale", unicode=1)
except IOError:
    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.typeHBox = xml.get_widget("typeHBox")
        self.selinuxTypeOptionMenu = xml.get_widget("selinuxTypeOptionMenu")
        self.typeLabel = xml.get_widget("typeLabel")
        self.enabledOptionMenu = xml.get_widget("enabledOptionMenu")
        self.currentOptionMenu = xml.get_widget("currentOptionMenu")
        self.relabel_checkbutton = xml.get_widget("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() == 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.MESSAGE_INFO,
                                gtk.BUTTONS_YES_NO,
                                message)
        dlg.set_position(gtk.WIN_POS_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.RESPONSE_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.RESPONSE_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.RESPONSE_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()]
