aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugeni Dodonov <eugeni@mandriva.org>2009-01-13 21:33:58 +0000
committerEugeni Dodonov <eugeni@mandriva.org>2009-01-13 21:33:58 +0000
commit55e810ab6a01a5157b7b43c186fb72753b2983a8 (patch)
tree4ba02d622ff1d0a0d4988bc637e593eb9f49b732
parentfc2c3bce9aabb18f2eb28bb7d140c64f18eb3975 (diff)
downloadmsec-55e810ab6a01a5157b7b43c186fb72753b2983a8.tar
msec-55e810ab6a01a5157b7b43c186fb72753b2983a8.tar.gz
msec-55e810ab6a01a5157b7b43c186fb72753b2983a8.tar.bz2
msec-55e810ab6a01a5157b7b43c186fb72753b2983a8.tar.xz
msec-55e810ab6a01a5157b7b43c186fb72753b2983a8.zip
Support for graphical level changes.
-rw-r--r--src/msec/config.py37
-rwxr-xr-xsrc/msec/msecgui.py216
2 files changed, 188 insertions, 65 deletions
diff --git a/src/msec/config.py b/src/msec/config.py
index ed4fc08..5e6f86d 100644
--- a/src/msec/config.py
+++ b/src/msec/config.py
@@ -107,6 +107,41 @@ SETTINGS = {'BASE_LEVEL': ("base_level",
'SHELL_HISTORY_SIZE': ("set_shell_history_size", ['*']),
'SHELL_TIMEOUT': ("set_shell_timeout", ['*']),
}
+# text for disabled options
+OPTION_DISABLED=_("Disabled")
+
+# localized help
+try:
+ from help import HELP
+except:
+ HELP = {}
+
+# helper function to find documentation for an option
+def find_doc(msec, option, cached=None):
+ """Helper function to find documentation for an option."""
+ if option not in SETTINGS:
+ # invalid option ?
+ return None
+ callback, values = SETTINGS[option]
+ # is it already cached?
+ if option in cached:
+ return cached[option]
+ if option in HELP:
+ doc = HELP[option]
+ else:
+ # option not found in HELP, lets look in docstring
+ # get description from function comments
+ func = msec.get_action(callback)
+ if func:
+ doc = func.__doc__.strip()
+ else:
+ # well, no luck. Just use the callback then
+ doc = callback
+ # updated cached values
+ if cached:
+ cached[option] = doc
+ return doc
+
# mandriva security tools
AUTH_NO_PASSWD = _("No password")
@@ -269,7 +304,7 @@ class MsecConfig:
value = self.options[option]
# prevent saving empty options
# TODO: integrate with remove()
- if value == None:
+ if value == None or value == OPTION_DISABLED:
self.log.debug("Skipping %s" % option)
else:
print >>fd, "%s=%s" % (option, self.options[option])
diff --git a/src/msec/msecgui.py b/src/msec/msecgui.py
index 0013d4e..b71bd47 100755
--- a/src/msec/msecgui.py
+++ b/src/msec/msecgui.py
@@ -37,12 +37,6 @@ try:
except IOError:
_ = str
-# localized help
-try:
- from help import HELP
-except:
- HELP = {}
-
# text strings
LEVEL_SECURITY_TEXT=_("""<big><b>Choose security level</b></big>
@@ -106,7 +100,7 @@ SAVE_SETTINGS_TEXT=_("""Save and apply new configuration?""")
class MsecGui:
"""Msec GUI"""
# common columns
- (COLUMN_OPTION, COLUMN_DESCR, COLUMN_VALUE) = range(3)
+ (COLUMN_OPTION, COLUMN_DESCR, COLUMN_VALUE, COLUMN_CUSTOM) = range(4)
(COLUMN_PATH, COLUMN_USER, COLUMN_GROUP, COLUMN_PERM, COLUMN_FORCE) = range(5)
(COLUMN_APP, COLUMN_DESCR, COLUMN_AUTH) = range(3)
@@ -136,6 +130,12 @@ class MsecGui:
)
}
+ # pre-load documentation for all possible options
+ self.descriptions = {}
+ for option in config.SETTINGS:
+ # get documentation for item
+ config.find_doc(msec, option, cached=self.descriptions)
+
# saving old config
self.oldconfig = {}
for opt in msecconfig.list_options():
@@ -218,19 +218,30 @@ class MsecGui:
self.notebook = gtk.Notebook()
main_vbox.add(self.notebook)
- self.notebook.append_page(self.level_security_page(), gtk.Label(_("Basic security")))
- self.notebook.append_page(self.auth_security_page(), gtk.Label(_("Authentication")))
- self.notebook.append_page(self.system_security_page(), gtk.Label(_("System security")))
- self.notebook.append_page(self.network_security_page(), gtk.Label(_("Network security")))
- self.notebook.append_page(self.periodic_security_page(), gtk.Label(_("Periodic checks")))
- self.notebook.append_page(self.notifications_page(), gtk.Label(_("Security notifications")))
- self.notebook.append_page(self.permissions_security_page(), gtk.Label(_("Permissions")))
+ # tabs to create in the intrerface
+ tabs = [
+ (1, self.level_security_page, _("Basic security")),
+ (2, self.auth_security_page, _("Authentication")),
+ (3, self.system_security_page, _("System security")),
+ (4, self.network_security_page, _("Network security")),
+ (5, self.periodic_security_page, _("Periodic checks")),
+ (6, self.notifications_page, _("Security notifications")),
+ (7, self.permissions_security_page, _("Permissions")),
+ ]
+ # data to change the values
+ self.current_options_view = {}
+ for id, callback, label in tabs:
+ self.notebook.append_page(callback(id), gtk.Label(label))
# are we enabled?
self.toggle_level(self.base_level)
self.window.show_all()
+ def recreate_tabs(self, notebook, tabs):
+ """Creates tabs and initializes options values"""
+ pass
+
def cancel(self, widget):
"""Cancel button"""
self.quit(widget)
@@ -241,13 +252,8 @@ class MsecGui:
def ok(self, widget):
"""Ok button"""
- # TODO: split in smaller functions
- print self.base_level
- self.log.debug(">> Enforcing level %s" % self.base_level)
- if self.base_level in self.defaults:
- curconfig, curperms = self.defaults[self.base_level]
- print curconfig.list_options()
- curperms = self.permconfig
+ curconfig = self.msecconfig
+ curperms = self.permconfig
# apply config and preview changes
self.log.start_buffer()
self.msec.apply(curconfig)
@@ -350,12 +356,8 @@ class MsecGui:
return
dialog.destroy()
- # rewriting configuration
- self.msecconfig.reset()
- self.msecconfig.merge(curconfig)
- self.permconfig.reset()
- self.permconfig.merge(curconfig)
-
+ # new base level
+ self.msecconfig.set("BASE_LEVEL", self.base_level)
# saving the configuration
self.msecconfig.save()
self.msec.apply(self.msecconfig)
@@ -382,7 +384,7 @@ class MsecGui:
gobject.TYPE_STRING,
gobject.TYPE_STRING,
gobject.TYPE_STRING,
- gobject.TYPE_STRING)
+ gobject.TYPE_BOOLEAN)
# treeview
treeview = gtk.TreeView(lstore)
@@ -411,6 +413,13 @@ class MsecGui:
column.set_sort_column_id(self.COLUMN_VALUE)
treeview.append_column(column)
+ # column for custom settings
+ column = gtk.TreeViewColumn(_('Customized'), gtk.CellRendererToggle(), active=self.COLUMN_CUSTOM)
+ column.set_sort_column_id(self.COLUMN_CUSTOM)
+ column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
+ column.set_fixed_width(50)
+ treeview.append_column(column)
+
sw.add(treeview)
for option in options:
@@ -421,30 +430,44 @@ class MsecGui:
continue
# getting level settings, callback and valid params
callback, params = config.SETTINGS[option]
- # getting the function description
- if option in HELP:
- self.log.debug("found localized help for %s" % option)
- doc = HELP[option]
- else:
- # get description from function comments
- func = self.msec.get_action(callback)
- if func:
- doc = func.__doc__.strip()
- else:
- doc = callback
# now for the value
value = self.msecconfig.get(option)
+ # check for disabled options
+ if not value:
+ value = config.OPTION_DISABLED
+
+ # description
+ doc = config.find_doc(self.msec, option, self.descriptions)
+
+ # was it changed? if yes, change description to italic
+ if self.option_is_changed(option, value):
+ custom = True
+ else:
+ custom = False
# building the option
iter = lstore.append()
- print iter
lstore.set(iter,
self.COLUMN_OPTION, option,
self.COLUMN_DESCR, doc,
self.COLUMN_VALUE, value,
+ self.COLUMN_CUSTOM, custom,
)
- return sw
+ return sw, lstore
+
+ def option_is_changed(self, option, value, level=None):
+ """Checks if the option is different from one specified by base level"""
+ if not level:
+ level = self.base_level
+ conf, perms = self.defaults[level]
+ if conf.get(option) != value:
+ # it was changed
+ print value
+ print conf.get(option)
+ return True
+ else:
+ return False
def create_auth_treeview(self, options):
"""Creates a treeview for authentication options"""
@@ -512,10 +535,10 @@ class MsecGui:
self.COLUMN_DESCR, descr,
self.COLUMN_AUTH, value,
)
- return sw
+ return sw, lstore
- def level_security_page(self):
+ def level_security_page(self, id):
"""Builds the basic security page"""
vbox = gtk.VBox(homogeneous=False)
@@ -551,7 +574,7 @@ class MsecGui:
return vbox
- def auth_security_page(self):
+ def auth_security_page(self, id):
"""Builds the authentication page"""
vbox = gtk.VBox(homogeneous=False)
@@ -569,12 +592,13 @@ class MsecGui:
sw.add_with_viewport(auth_vbox)
vbox.add(sw)
- apps = self.create_auth_treeview(config.MANDRIVA_TOOL_GROUPS)
+ apps, model = self.create_auth_treeview(config.MANDRIVA_TOOL_GROUPS)
auth_vbox.pack_start(apps)
+ self.current_options_view[id] = (model, self.authconfig)
return vbox
- def toggle_level(self, level):
+ def toggle_level(self, level, force=False):
"""Enables/disables graphical items for msec"""
if level != config.NONE_LEVEL:
enabled = True
@@ -589,17 +613,45 @@ class MsecGui:
label = self.notebook.get_tab_label(curpage)
label.set_sensitive(enabled)
- # TODO: update all widgets
+ # what is the current level?
+ defconfig, defperms = self.defaults[level]
+
+ for z in self.current_options_view:
+ print z
+ options, curconfig = self.current_options_view[z]
+ iter = options.get_iter_root()
+ # what options are we changing
+ if curconfig.__class__ == config.MsecConfig:
+ # main msec options
+ while iter:
+ option = options.get_value(iter, self.COLUMN_OPTION)
+ curvalue = options.get_value(iter, self.COLUMN_VALUE)
+ newvalue = defconfig.get(option)
+ if curvalue != newvalue:
+ # changing option
+ print "%s: %s -> %s" % (option, curvalue, newvalue)
+ options.set(iter, self.COLUMN_VALUE, newvalue)
+ curconfig.set(option, newvalue)
+ ## skip custom options
+ #print "Base level: %s" % self.base_level
+ #if self.option_is_changed(option, curvalue):
+ # # custom option
+ # print "Custom option detected: %s" % option
+ iter = options.iter_next(iter)
+ else:
+ print curconfig.__class__
+ # finally, change new base_level
+ self.base_level = level
def force_level(self, widget, level):
"""Defines a given security level"""
if widget.get_active():
- self.base_level = level
+ #self.base_level = level
# update everything
- print level
- self.toggle_level(level)
+ print "Forcing level %s" % level
+ self.toggle_level(level, force=True)
- def notifications_page(self):
+ def notifications_page(self, id):
"""Builds the notifications page"""
vbox = gtk.VBox(homogeneous=False)
@@ -610,12 +662,15 @@ class MsecGui:
vbox.pack_start(entry, False, False)
# basic security options
- options_view = self.create_treeview(["TTY_WARN", "SYSLOG_WARN", "NOTIFY_WARN", "MAIL_WARN", "MAIL_USER", "MAIL_EMPTY_CONTENT"])
+ options_view, model = self.create_treeview(["TTY_WARN", "SYSLOG_WARN", "NOTIFY_WARN", "MAIL_WARN", "MAIL_USER", "MAIL_EMPTY_CONTENT"])
+
+ # save those options
+ self.current_options_view[id] = (model, self.msecconfig)
vbox.pack_start(options_view)
return vbox
- def system_security_page(self):
+ def system_security_page(self, id):
"""Builds the network security page"""
vbox = gtk.VBox(homogeneous=False)
@@ -624,7 +679,7 @@ class MsecGui:
vbox.pack_start(entry, False, False)
# system security options
- options_view = self.create_treeview(["ENABLE_APPARMOR", "ENABLE_POLICYKIT",
+ options_view, model = self.create_treeview(["ENABLE_APPARMOR", "ENABLE_POLICYKIT",
"ENABLE_SUDO", "ENABLE_MSEC_CRON", "ENABLE_PAM_WHEEL_FOR_SU",
"ENABLE_SULOGIN", "CREATE_SERVER_LINK", "ENABLE_AT_CRONTAB",
"ALLOW_ROOT_LOGIN", "ALLOW_USER_LIST", "ENABLE_PASSWORD",
@@ -633,11 +688,12 @@ class MsecGui:
"ALLOW_REBOOT", "SHELL_HISTORY_SIZE", "SHELL_TIMEOUT", "PASSWORD_LENGTH",
"PASSWORD_HISTORY", "USER_UMASK", "ROOT_UMASK",
])
+ self.current_options_view[id] = (model, self.msecconfig)
vbox.pack_start(options_view)
return vbox
- def network_security_page(self):
+ def network_security_page(self, id):
"""Builds the network security page"""
vbox = gtk.VBox(homogeneous=False)
@@ -646,17 +702,18 @@ class MsecGui:
vbox.pack_start(entry, False, False)
# network security options
- options_view = self.create_treeview(["ACCEPT_BOGUS_ERROR_RESPONSES", "ACCEPT_BROADCASTED_ICMP_ECHO",
+ options_view, model = self.create_treeview(["ACCEPT_BOGUS_ERROR_RESPONSES", "ACCEPT_BROADCASTED_ICMP_ECHO",
"ACCEPT_ICMP_ECHO", "ALLOW_REMOTE_ROOT_LOGIN",
"ALLOW_X_CONNECTIONS", "ALLOW_XSERVER_TO_LISTEN",
"AUTHORIZE_SERVICES", "ENABLE_DNS_SPOOFING_PROTECTION",
"ENABLE_IP_SPOOFING_PROTECTION", "ENABLE_LOG_STRANGE_PACKETS",
])
+ self.current_options_view[id] = (model, self.msecconfig)
vbox.pack_start(options_view)
return vbox
- def periodic_security_page(self):
+ def periodic_security_page(self, id):
"""Builds the network security page"""
vbox = gtk.VBox(homogeneous=False)
@@ -669,7 +726,7 @@ class MsecGui:
vbox.pack_start(self.periodic_checks, False, False)
# network security options
- options_view = self.create_treeview(["CHECK_PERMS", "CHECK_USER_FILES", "CHECK_SUID_ROOT", "CHECK_SUID_MD5",
+ options_view, model = self.create_treeview(["CHECK_PERMS", "CHECK_USER_FILES", "CHECK_SUID_ROOT", "CHECK_SUID_MD5",
"CHECK_SGID", "CHECK_WRITABLE", "CHECK_UNOWNED",
"CHECK_PROMISC", "CHECK_OPEN_PORT", "CHECK_PASSWD",
"CHECK_SHADOW", "CHECK_CHKROOTKIT", "CHECK_RPM",
@@ -683,6 +740,8 @@ class MsecGui:
if periodic_checks == 'no':
# disable all periodic tests
options_view.set_sensitive(False)
+ # TODO: CHECK_SECURITY??
+ self.current_options_view[id] = (model, self.msecconfig)
return vbox
@@ -696,7 +755,7 @@ class MsecGui:
self.msecconfig.set("CHECK_SECURITY", "no")
options.set_sensitive(False)
- def permissions_security_page(self):
+ def permissions_security_page(self, id):
"""Builds the network security page"""
vbox = gtk.VBox(homogeneous=False)
@@ -752,7 +811,6 @@ class MsecGui:
column.set_sort_column_id(self.COLUMN_FORCE)
column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
column.set_fixed_width(50)
-
treeview.append_column(column)
sw.add(treeview)
@@ -776,6 +834,7 @@ class MsecGui:
self.COLUMN_FORCE, force,
)
vbox.pack_start(sw)
+ self.current_options_view[id] = (lstore, self.permconfig)
return vbox
def toggle_enforced(self, cell, path, model):
@@ -869,25 +928,45 @@ class MsecGui:
descr = model.get_value(iter, self.COLUMN_DESCR)
value = model.get_value(iter, self.COLUMN_VALUE)
+ # option is disabled?
+ if not value:
+ value = config.OPTION_DISABLED
+
callback, params = config.SETTINGS[param]
+ conf_def, perms = self.defaults[config.DEFAULT_LEVEL]
+ conf_sec, perms = self.defaults[config.SECURE_LEVEL]
+
+ val_def = conf_def.get(param)
+ val_sec = conf_sec.get(param)
# asks for new parameter value
dialog = gtk.Dialog(_("Select new value for %s") % (param),
self.window, 0,
(gtk.STOCK_OK, gtk.RESPONSE_OK,
gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
- label = gtk.Label(_("Modifying <b>%s</b>.\n<i>%s</i>\nCurrent value: <b>%s</b>") % (param, descr, value))
+ # option title
+ label = gtk.Label("<b>%s</b>\n" % param)
+ label.set_use_markup(True)
+ # description
+ dialog.vbox.pack_start(label)
+ label = gtk.Label(_("<i>%s</i>\n\n\tCurrent value: <b>%s</b>\n\tDefault level value: <b>%s</b>\n\tSecure level value: <b>%s</b>\n") % (descr, value, val_def, val_sec))
label.set_line_wrap(True)
label.set_use_markup(True)
dialog.vbox.pack_start(label)
+ dialog.vbox.pack_start(gtk.HSeparator())
+
+ # new value
+ hbox = gtk.HBox()
+ hbox.pack_start(gtk.Label(_("New value:")))
if '*' in params:
# string parameter
entry = gtk.Entry()
entry.set_text(value)
- dialog.vbox.pack_start(entry)
else:
# combobox parameter
entry = gtk.combo_box_new_text()
+ # add an item to disable a check
+ params.append(config.OPTION_DISABLED)
for item in params:
entry.append_text(item)
if value not in params:
@@ -895,7 +974,8 @@ class MsecGui:
params.append(value)
active = params.index(value)
entry.set_active(active)
- dialog.vbox.pack_start(entry)
+ hbox.pack_start(entry)
+ dialog.vbox.pack_start(hbox)
dialog.show_all()
response = dialog.run()
@@ -908,13 +988,21 @@ class MsecGui:
newval = entry.get_text()
else:
newval = entry.get_active_text()
- newval = entry.get_active_text()
dialog.destroy()
# update options
self.msecconfig.set(param, newval)
+ # is it different from default? if yes, change description to italic
+ doc = config.find_doc(self.msec, param, self.descriptions)
+ if self.option_is_changed(param, newval):
+ custom = True
+ else:
+ custom = False
+
model.set(iter, self.COLUMN_VALUE, newval)
+ model.set(iter, self.COLUMN_DESCR, doc)
+ model.set(iter, self.COLUMN_CUSTOM, custom)
def auth_changed(self, treeview, path, col, model):