Viewing file: securitylevel.py (22.01 KB) -rwxr-xr-x Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# # securitylevel.py - GUI front end code for basic system security # # Brent Fox <bfox@redhat.com> # # Copyright 2002, 2003, 2004 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. #
import string import gtk import gtk.glade import gobject import sys import os import socket sys.path.append('/usr/share/system-config-securitylevel') import scs_checklist as checklist import trustedchecklist import selinuxPage import types
## ## I18N ## from rhpl.translate import _, N_ import rhpl.translate as translate domain = "system-config-securitylevel" translate.textdomain (domain)
## ## Icon for windows ##
iconPixbuf = None try: iconPixbuf = gtk.gdk.pixbuf_new_from_file("/usr/share/system-config-securitylevel/pixmaps/system-config-securitylevel.png") except: pass
## ## Pull in the Glade file ## if os.access("system-config-securitylevel.glade", os.F_OK): xml = gtk.glade.XML ("system-config-securitylevel.glade", domain=domain) else: xml = gtk.glade.XML ("/usr/share/system-config-securitylevel/system-config-securitylevel.glade", domain=domain)
class childWindow: # You must specify a runPriority for the firstboot module order runPriority = 50 moduleName = _("Firewall") commentTag = _("Configure system security level and firewall rules") shortMessage = _("You can use a firewall to allow access to specific " "services on your computer from other computers and " "prevent unauthorized access from the outside world. " "Which services, if any, do you wish to allow access to?")
def destroy(self, args): gtk.main_quit()
def __init__(self): self.xml = xml self.dirty = False self.doDebug = None self.selinuxPage = None self.other_changed_firsttime = True self.serviceDict = \ {"SSH": {"ports": [("ssh", "tcp")], "modules": []}, "Telnet": {"ports": [("telnet", "tcp")], "modules": []}, "WWW (HTTP)": {"ports": [("http", "tcp")], "modules": []}, "FTP": {"ports": [("ftp", "tcp")], "modules": ["ip_conntrack_ftp"]}, "NFS4": {"ports": [("nfs", "tcp")], "modules": []}, _("Secure WWW (HTTPS)"): {"ports": [("https", "tcp")], "modules": []}, _("Mail (SMTP)"): {"ports": [("smtp", "tcp")], "modules": []}, _("Samba"): {"ports": [("137", "udp"), ("138", "udp"), ("139", "tcp"), ("445", "tcp")], "modules": []}}
def setupScreen(self): # Bring in widgets from glade file. self.incomingSW = self.xml.get_widget("incomingSW") self.mainVBox = self.xml.get_widget("mainVBox") self.mainWindow = self.xml.get_widget("mainWindow") self.notebook = self.xml.get_widget("scsNotebook") self.securityOptionMenu = self.xml.get_widget("securityOptionMenu") self.seLinuxVBox = self.xml.get_widget("seLinuxVBox") self.otherPortsView = self.xml.get_widget("otherPortsView")
self.trustedServicesBox = self.xml.get_widget("trustedServicesBox") self.otherPortsExpander = self.xml.get_widget("otherPortsExpander")
self.addPortButton = self.xml.get_widget("addPortButton") self.removePortButton = self.xml.get_widget("removePortButton")
self.addPortDialog = self.xml.get_widget("addPortDialog") self.addPortTable = self.xml.get_widget("addPortTable") self.portEntry = self.xml.get_widget("portEntry")
self.mainWindow.set_icon(iconPixbuf)
# Set up the enabled/disabled firewall combo box. listStore = gtk.ListStore(gobject.TYPE_STRING) self.securityOptionMenu.set_model(listStore) cell = gtk.CellRendererText() self.securityOptionMenu.pack_start(cell, True) self.securityOptionMenu.add_attribute(cell, 'text', 0)
self.security_changed_firsttime = True self.securityOptionMenu.connect('changed', self.security_changed_cb) self.securityOptionMenu.append_text(_("Enabled")) self.securityOptionMenu.append_text(_("Disabled"))
# Set up the trusted services checklist. self.incomingList = checklist.CheckList(columns=1) keyList = self.serviceDict.keys() keyList.sort()
for item in keyList: self.incomingList.append_row((item, ""), False) self.incomingSW.add(self.incomingList)
# Set up the view and columns for the Other Ports section. self.otherPortsStore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) otherPortsSorted = gtk.TreeModelSort(self.otherPortsStore) otherPortsSorted.set_sort_column_id(0, gtk.SORT_ASCENDING) self.otherPortsView.set_model(otherPortsSorted)
portsCol = gtk.TreeViewColumn("Ports", gtk.CellRendererText(), text=0) portsCol.set_expand(True) self.otherPortsView.append_column(portsCol) protoCol = gtk.TreeViewColumn("Proto", gtk.CellRendererText(), text=1) self.otherPortsView.append_column(protoCol)
self.addPortButton.connect("clicked", self.add_port_cb) self.removePortButton.connect("clicked", self.remove_port_cb)
# Add buttons to the "Add Port" dialog, since they don't want to # behave otherwise. self.addPortDialog.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)
# Add options to the protocol combo box. self.protoCombo = gtk.combo_box_new_text() self.addPortTable.attach(self.protoCombo, 1, 2, 1, 2) self.protoCombo.append_text("tcp") self.protoCombo.append_text("udp") self.protoCombo.set_active(0)
def firewall_activated(self, *args): self.trustedServicesBox.set_sensitive(True) self.otherPortsExpander.set_sensitive(True) self.dirty = True
def none_activated(self, *args): self.trustedServicesBox.set_sensitive(False) self.otherPortsExpander.set_sensitive(False) self.dirty = True
def add_port_cb(self, button, *args): protoMapping = ["tcp", "udp"]
self.addPortDialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.addPortDialog.set_transient_for(self.mainWindow) self.addPortDialog.set_modal(True) self.addPortDialog.show_all() self.portEntry.set_text("") self.protoCombo.set_active(0)
# Loop until we get a valid port string. while True: result = self.addPortDialog.run()
if result == gtk.RESPONSE_OK: portStr = self.portEntry.get_text() proto = protoMapping[self.protoCombo.get_active()]
ports = self.portIsValid(portStr) if not ports: self.invalidPortDialog(portStr) continue else: portStr = ports if self.findPortInStore(portStr, proto) is None: self.otherPortsStore.append([portStr, proto]) self.dirty = True break else: break
self.addPortDialog.hide()
def remove_port_cb(self, button, *args): selection = self.otherPortsView.get_selection() (model, treeModelSortIter) = selection.get_selected()
if treeModelSortIter is None: return
# Convert the iter on the TreeModelSort to an iter on the underlying # ListStore so we can delete the right thing. iter = model.convert_iter_to_child_iter(None, treeModelSortIter)
if iter is not None: # Need to get past the TreeModelSort to whatever's underneath. model.get_model().remove(iter) self.dirty = True
def security_changed_cb(self, combobox, *args): if self.security_changed_firsttime == True: self.security_changed_firsttime = False return model = combobox.get_model() active = combobox.get_active() if active < 0: return None elif active == 0: self.firewall_activated() elif active == 1: self.none_activated() else: return None
def other_changed_cb(self, *args): if self.other_changed_firsttime == True: self.other_changed_firsttime = False return self.dirty = True
def okClicked(self, *args): rc = self.apply() if rc == 0: self.destroy(args)
def applyClicked(self, *args): self.apply()
def readFile(self): path = "/etc/sysconfig/system-config-securitylevel" if os.access(path, os.R_OK) == 1: lines = open(path, 'r').readlines() else: #The file isn't there, so just return and keep on going self.trustedServicesBox.set_sensitive(True) self.otherPortsExpander.set_sensitive(True) return
devicesList = [] masqList = [] servicesList = [] portsList = []
# Special list so we can infer Samba browsing being enabled if all # the ports are enabled. sambaList = []
self.trustedServicesBox.set_sensitive(True) self.otherPortsExpander.set_sensitive(True)
for line in lines: stripped = string.strip(line)
if stripped != "" and stripped[0] != "#": if stripped in ["--high", "--medium", "--enabled"]: self.securityOptionMenu.set_active(0) elif stripped == "--disabled": self.securityOptionMenu.set_active(1) self.trustedServicesBox.set_sensitive(False) self.otherPortsExpander.set_sensitive(False) elif line[:8] == "--trust=": key, device = string.split(line, "=") devicesList.append(string.strip(device)) elif line[:7] == "--masq=": key, device = string.split(line, "=") masqList.append(string.strip(device)) elif line[:7] == "--port=": key, value = string.split(line, "=")
try: service, protocol = string.split(value, ":") except ValueError: service = value protocol = "tcp"
service = string.strip(service) protocol = string.strip(protocol) if service in ["22", "ssh"]: service = 'ssh' elif service in ["80", "http"]: service = 'http' elif service in ["443", "https"]: service = 'https' elif service in ["23", "telnet"]: service = 'telnet' elif service in ["21", "ftp"]: service = 'ftp' elif service in ["25", "smtp"]: service = 'smtp' elif service in ["2049", "nfs"]: service = 'nfs' else: # Catch ports that aren't in /etc/services. try: protoname = socket.getservbyport(int(service), protocol) except: protoname = service
# Use the translated names anyway, in case we're # only enabling some of these ports and not samba. if service == '137' and protocol == 'udp' or \ service == '138' and protocol == 'udp' or \ service == '139' and protocol == 'tcp' or \ service == '445' and protocol == 'tcp': sambaList.append(protoname + ":" + protocol) else: portsList.append(protoname + ":" + protocol)
continue servicesList.append(service)
# Lame. If all the ports were added for Samba browsing, add it to # the incomingList instead of adding the ports to the portsList. # This would be easier if we had a --service option or similar # that stood for a set of ports, rather than specify each one. if len(sambaList) == 4: iter = self.incomingList.store.get_iter_first() while iter: if self.incomingList.store.get_value(iter, 1) == _("Samba"): self.incomingList.store.set_value(iter, 0, True) break iter = self.incomingList.store.iter_next(iter) else: portsList.extend (sambaList)
iter = self.incomingList.store.get_iter_first() while iter: val = self.incomingList.store.get_value(iter, 1) for (port, proto) in self.serviceDict[val]["ports"]: if port in servicesList: self.incomingList.store.set_value(iter, 0, True)
iter = self.incomingList.store.iter_next(iter)
# Add the enabled other ports to the view. for pair in portsList: (port, proto) = pair.split(':') port = self.portIsValid(port) if port and proto in ["tcp", "udp"]: self.otherPortsStore.append([port, proto])
def findPortInStore(self, port, proto): iter = self.otherPortsStore.get_iter_first() while iter: if port == self.otherPortsStore.get_value(iter, 0) and \ proto == self.otherPortsStore.get_value(iter, 1): return iter else: iter = self.otherPortsStore.iter_next(iter)
return None
def getPortID(self, port): try: id = int(port) except: try: id = socket.getservbyname(port) except: return -1 if id > 65535: return -1 return id
def getPortRange(self, ports): splits = ports.split("-") matched = [ ] for i in xrange(len(splits), 0, -1): id1 = self.getPortID("-".join(splits[:i])) port2 = "-".join(splits[i:]) if len(port2) > 0: id2 = self.getPortID(port2) if id1 >= 0 and id2 >= 0: if id1 <= id2: matched.append((id1, id2)) else: matched.append((id2, id1)) else: if id1 >= 0: matched.append((id1,)) if i == len(splits): # full match, stop here break if len(matched) < 1: return -1 elif len(matched) > 1: return None return matched[0]
def portIsValid(self, port): ports = self.getPortRange(port) if not (isinstance(ports, types.ListType) or \ isinstance(ports, types.TupleType)): return None if len(ports) == 1: return "%d" % ports[0] return "%d-%d" % (ports[0], ports[1])
def invalidPortDialog(self, port): text = _("Invalid port given: '%s'. Please give a port number " "or service name.") % port
dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, text) dlg.set_modal(True) dlg.set_icon(iconPixbuf) dlg.set_position(gtk.WIN_POS_CENTER_ON_PARENT) dlg.set_transient_for(self.mainWindow) dlg.show_all() dlg.run() dlg.destroy()
def confirmDialog(self): dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO, _("Clicking the 'Yes' button will set the security level of the " "system and override any " "existing firewall configuration. Are you sure that you want " "to do this?")) dlg.set_position(gtk.WIN_POS_CENTER_ON_PARENT) dlg.set_transient_for(self.mainWindow) dlg.set_modal(True) dlg.set_icon(iconPixbuf) dlg.show_all() result = dlg.run() dlg.destroy() return result
def apply(self, *args): if self.selinuxPage and self.selinuxPage.selinuxsupport: self.selinuxPage.apply()
if self.dirty != True and self.incomingList.dirty != True: return 0
# With the new enabled/disabled behavior, we have to ignore the config # file or else you can only ever turn on services. args = ['/usr/sbin/lokkit', '--quiet', '-f']
index = self.securityOptionMenu.get_active() if index == 0: args.append('--enabled') elif index == 1: args.append('--disabled')
count = 0 keyList = self.serviceDict.keys() keyList.sort()
for service in keyList: if self.incomingList.get_active(count): for (port, proto) in self.serviceDict[service]["ports"]: args.append('--port=' + port + ':' + proto) for module in self.serviceDict[service]["modules"]: args.append('--addmodule=' + module) else: for module in self.serviceDict[service]["modules"]: args.append('--removemodule=' + module) count = count + 1
model = self.otherPortsView.get_model() iter = model.get_iter_first()
while iter: args.append("--port=%s:%s" % (model.get_value(iter, 0), model.get_value(iter, 1))) iter = model.iter_next(iter)
if self.confirmDialog() == gtk.RESPONSE_NO: return None
if self.doDebug: print "don't call lokkit if in debug mode" else: (rfd, wfd) = os.pipe() pid = os.fork() if pid == 0: try: os.close(rfd) fd = os.open("/dev/null", os.O_RDONLY) if fd != 0: os.dup2(fd, 0) os.close(fd) if wfd != 1: os.dup2(wfd, 1) os.close(wfd) os.dup2(1, 2) os.execv(args[0], args) finally: os._exit(255)
os.close(wfd) # no need to read in chunks if we don't pass on data to some # output func cret = "" cout = os.read(rfd, 8192) while cout: cret += cout cout = os.read(rfd, 8192) os.close(rfd) (cpid, status) = os.waitpid(pid, 0)
# failed to configure firewall, show error message if status != 0: dialog = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE) dialog.set_markup("<b>" + _("Configuration failed") + \ "</b>") dialog.format_secondary_text(" ".join(args) + "\n\n" + \ cret.strip()) dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT) dialog.set_transient_for(self.mainWindow) dialog.set_modal(True) dialog.show_all() dialog.run() dialog.destroy() return 1
# Set these to False so if you click Apply followed by OK, you're not # prompted twice. self.dirty = False self.incomingList.dirty = False return 0
def launch(self, doDebug = None): self.doDebug = doDebug self.setupScreen()
messageLabel = gtk.Label(_(self.shortMessage)) messageLabel.set_line_wrap(True) messageLabel.set_size_request(500, -1) messageLabel.set_alignment(0.0, 0.5)
self.readFile() vbox = gtk.VBox(spacing=10) vbox.pack_start(messageLabel, expand=False) self.mainVBox.reparent(vbox)
icon = gtk.Image() icon.set_from_pixbuf(iconPixbuf) return vbox, icon, self.moduleName
def stand_alone(self): desktopName = _("Security Level and Firewall")
self.setupScreen() self.okButton = self.xml.get_widget("okButton") self.cancelButton = self.xml.get_widget("cancelButton") self.applyButton = self.xml.get_widget("applyButton") self.selinuxPage = selinuxPage.selinuxPage(xml)
self.mainWindow.connect("destroy", self.destroy) self.okButton.connect("clicked", self.okClicked) self.cancelButton.connect("clicked", self.destroy) self.applyButton.connect("clicked", self.applyClicked)
# Put labels on the notebook tabs since gazpacho doesn't provide a # way to do that right now. firewallLabel = gtk.Label(_("_Firewall Options")) firewallLabel.set_use_underline(True) self.notebook.set_tab_label(self.mainVBox, firewallLabel) selinuxLabel = gtk.Label(_("_SELinux")) selinuxLabel.set_use_underline(True) self.notebook.set_tab_label(self.seLinuxVBox, selinuxLabel)
self.readFile() self.mainWindow.show_all() gtk.main()
|