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