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