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