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