1## portsPage.py - show selinux mappings 2## Copyright (C) 2006 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 string 20import gtk 21import gtk.glade 22import os 23import gobject 24import sys 25import seobject 26 27TYPE_COL = 0 28PROTOCOL_COL = 1 29MLS_COL = 2 30PORT_COL = 3 31 32try: 33 from subprocess import getstatusoutput 34except ImportError: 35 from commands import getstatusoutput 36 37from semanagePage import * 38 39## 40## I18N 41## 42PROGNAME = "policycoreutils" 43try: 44 import gettext 45 kwargs = {} 46 if sys.version_info < (3,): 47 kwargs['unicode'] = True 48 gettext.install(PROGNAME, 49 localedir="/usr/share/locale", 50 codeset='utf-8', 51 **kwargs) 52except: 53 try: 54 import builtins 55 builtins.__dict__['_'] = str 56 except ImportError: 57 import __builtin__ 58 __builtin__.__dict__['_'] = unicode 59 60 61class portsPage(semanagePage): 62 63 def __init__(self, xml): 64 semanagePage.__init__(self, xml, "ports", _("Network Port")) 65 xml.signal_connect("on_group_clicked", self.on_group_clicked) 66 self.group = False 67 self.ports_filter = xml.get_widget("portsFilterEntry") 68 self.ports_filter.connect("focus_out_event", self.filter_changed) 69 self.ports_filter.connect("activate", self.filter_changed) 70 self.ports_name_entry = xml.get_widget("portsNameEntry") 71 self.ports_protocol_combo = xml.get_widget("portsProtocolCombo") 72 self.ports_number_entry = xml.get_widget("portsNumberEntry") 73 self.ports_mls_entry = xml.get_widget("portsMLSEntry") 74 self.ports_add_button = xml.get_widget("portsAddButton") 75 self.ports_properties_button = xml.get_widget("portsPropertiesButton") 76 self.ports_delete_button = xml.get_widget("portsDeleteButton") 77 liststore = self.ports_protocol_combo.get_model() 78 iter = liststore.get_iter_first() 79 self.ports_protocol_combo.set_active_iter(iter) 80 self.init_store() 81 self.edit = True 82 self.load() 83 84 def filter_changed(self, *arg): 85 filter = arg[0].get_text() 86 if filter != self.filter: 87 if self.edit: 88 self.load(filter) 89 else: 90 self.group_load(filter) 91 92 def init_store(self): 93 self.store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) 94 self.view.set_model(self.store) 95 self.store.set_sort_column_id(0, gtk.SORT_ASCENDING) 96 97 self.view.set_search_equal_func(self.search) 98 col = gtk.TreeViewColumn(_("SELinux Port\nType"), gtk.CellRendererText(), text=TYPE_COL) 99 col.set_sort_column_id(TYPE_COL) 100 col.set_resizable(True) 101 self.view.append_column(col) 102 self.store.set_sort_column_id(TYPE_COL, gtk.SORT_ASCENDING) 103 104 col = gtk.TreeViewColumn(_("Protocol"), gtk.CellRendererText(), text=PROTOCOL_COL) 105 col.set_sort_column_id(PROTOCOL_COL) 106 col.set_resizable(True) 107 self.view.append_column(col) 108 109 self.mls_col = gtk.TreeViewColumn(_("MLS/MCS\nLevel"), gtk.CellRendererText(), text=MLS_COL) 110 self.mls_col.set_resizable(True) 111 self.mls_col.set_sort_column_id(MLS_COL) 112 self.view.append_column(self.mls_col) 113 114 col = gtk.TreeViewColumn(_("Port"), gtk.CellRendererText(), text=PORT_COL) 115 col.set_sort_column_id(PORT_COL) 116 col.set_resizable(True) 117 self.view.append_column(col) 118 self.store.set_sort_func(PORT_COL, self.sort_int, "") 119 120 def sort_int(self, treemodel, iter1, iter2, user_data): 121 try: 122 p1 = int(treemodel.get_value(iter1, PORT_COL).split('-')[0]) 123 p2 = int(treemodel.get_value(iter2, PORT_COL).split('-')[0]) 124 if p1 > p2: 125 return 1 126 if p1 == p2: 127 return 0 128 return -1 129 except: 130 return 0 131 132 def load(self, filter=""): 133 self.filter = filter 134 self.port = seobject.portRecords() 135 dict = self.port.get_all(self.local) 136 self.store.clear() 137 for k in sorted(dict.keys()): 138 if not (self.match(str(k[0]), filter) or self.match(dict[k][0], filter) or self.match(k[2], filter) or self.match(dict[k][1], filter) or self.match(dict[k][1], filter)): 139 continue 140 iter = self.store.append() 141 if k[0] == k[1]: 142 self.store.set_value(iter, PORT_COL, k[0]) 143 else: 144 rec = "%s-%s" % k[:2] 145 self.store.set_value(iter, PORT_COL, rec) 146 self.store.set_value(iter, TYPE_COL, dict[k][0]) 147 self.store.set_value(iter, PROTOCOL_COL, k[2]) 148 self.store.set_value(iter, MLS_COL, dict[k][1]) 149 self.view.get_selection().select_path((0,)) 150 151 def group_load(self, filter=""): 152 self.filter = filter 153 self.port = seobject.portRecords() 154 dict = self.port.get_all_by_type(self.local) 155 self.store.clear() 156 for k in sorted(dict.keys()): 157 ports_string = ", ".join(dict[k]) 158 if not (self.match(ports_string, filter) or self.match(k[0], filter) or self.match(k[1], filter)): 159 continue 160 iter = self.store.append() 161 self.store.set_value(iter, TYPE_COL, k[0]) 162 self.store.set_value(iter, PROTOCOL_COL, k[1]) 163 self.store.set_value(iter, PORT_COL, ports_string) 164 self.store.set_value(iter, MLS_COL, "") 165 self.view.get_selection().select_path((0,)) 166 167 def propertiesDialog(self): 168 if self.edit: 169 semanagePage.propertiesDialog(self) 170 171 def dialogInit(self): 172 store, iter = self.view.get_selection().get_selected() 173 self.ports_number_entry.set_text(store.get_value(iter, PORT_COL)) 174 self.ports_number_entry.set_sensitive(False) 175 self.ports_protocol_combo.set_sensitive(False) 176 self.ports_name_entry.set_text(store.get_value(iter, TYPE_COL)) 177 self.ports_mls_entry.set_text(store.get_value(iter, MLS_COL)) 178 protocol = store.get_value(iter, PROTOCOL_COL) 179 liststore = self.ports_protocol_combo.get_model() 180 iter = liststore.get_iter_first() 181 while iter != None and liststore.get_value(iter, 0) != protocol: 182 iter = liststore.iter_next(iter) 183 if iter != None: 184 self.ports_protocol_combo.set_active_iter(iter) 185 186 def dialogClear(self): 187 self.ports_number_entry.set_text("") 188 self.ports_number_entry.set_sensitive(True) 189 self.ports_protocol_combo.set_sensitive(True) 190 self.ports_name_entry.set_text("") 191 self.ports_mls_entry.set_text("s0") 192 193 def delete(self): 194 store, iter = self.view.get_selection().get_selected() 195 port = store.get_value(iter, PORT_COL) 196 protocol = store.get_value(iter, 1) 197 try: 198 self.wait() 199 (rc, out) = getstatusoutput("semanage port -d -p %s %s" % (protocol, port)) 200 self.ready() 201 if rc != 0: 202 return self.error(out) 203 store.remove(iter) 204 self.view.get_selection().select_path((0,)) 205 except ValueError as e: 206 self.error(e.args[0]) 207 208 def add(self): 209 target = self.ports_name_entry.get_text().strip() 210 mls = self.ports_mls_entry.get_text().strip() 211 port_number = self.ports_number_entry.get_text().strip() 212 if port_number == "": 213 port_number = "1" 214 for i in port_number.split("-"): 215 if not i.isdigit(): 216 self.error(_("Port number \"%s\" is not valid. 0 < PORT_NUMBER < 65536 ") % port_number) 217 return False 218 list_model = self.ports_protocol_combo.get_model() 219 iter = self.ports_protocol_combo.get_active_iter() 220 protocol = list_model.get_value(iter, 0) 221 self.wait() 222 (rc, out) = getstatusoutput("semanage port -a -p %s -r %s -t %s %s" % (protocol, mls, target, port_number)) 223 self.ready() 224 if rc != 0: 225 self.error(out) 226 return False 227 iter = self.store.append() 228 229 self.store.set_value(iter, TYPE_COL, target) 230 self.store.set_value(iter, PORT_COL, port_number) 231 self.store.set_value(iter, PROTOCOL_COL, protocol) 232 self.store.set_value(iter, MLS_COL, mls) 233 234 def modify(self): 235 target = self.ports_name_entry.get_text().strip() 236 mls = self.ports_mls_entry.get_text().strip() 237 port_number = self.ports_number_entry.get_text().strip() 238 list_model = self.ports_protocol_combo.get_model() 239 iter = self.ports_protocol_combo.get_active_iter() 240 protocol = list_model.get_value(iter, 0) 241 self.wait() 242 (rc, out) = getstatusoutput("semanage port -m -p %s -r %s -t %s %s" % (protocol, mls, target, port_number)) 243 self.ready() 244 if rc != 0: 245 self.error(out) 246 return False 247 store, iter = self.view.get_selection().get_selected() 248 self.store.set_value(iter, TYPE_COL, target) 249 self.store.set_value(iter, PORT_COL, port_number) 250 self.store.set_value(iter, PROTOCOL_COL, protocol) 251 self.store.set_value(iter, MLS_COL, mls) 252 253 def on_group_clicked(self, button): 254 self.ports_add_button.set_sensitive(self.group) 255 self.ports_properties_button.set_sensitive(self.group) 256 self.ports_delete_button.set_sensitive(self.group) 257 self.mls_col.set_visible(self.group) 258 259 self.group = not self.group 260 if self.group: 261 button.set_label(_("List View")) 262 self.group_load(self.filter) 263 else: 264 button.set_label(_("Group View")) 265 self.load(self.filter) 266 267 return True 268