1#!/usr/bin/python3 -Es 2# 3# polgengui.py - GUI for SELinux Config tool in system-config-selinux 4# 5# Dan Walsh <dwalsh@redhat.com> 6# 7# Copyright (C) 2007-2013 Red Hat 8# 9# This program is free software; you can redistribute it and/or modify 10# it under the terms of the GNU General Public License as published by 11# the Free Software Foundation; either version 2 of the License, or 12# (at your option) any later version. 13# 14# This program is distributed in the hope that it will be useful, 15# but WITHOUT ANY WARRANTY; without even the implied warranty of 16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17# GNU General Public License for more details. 18# 19# You should have received a copy of the GNU General Public License 20# along with this program; if not, write to the Free Software 21# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22# 23import signal 24import string 25import gi 26gi.require_version('Gtk', '3.0') 27from gi.repository import Gtk 28import os 29from gi.repository import GObject 30import sys 31try: 32 import sepolicy 33except ValueError as e: 34 sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e))) 35 sys.exit(1) 36 37import sepolicy.generate 38import sepolicy.interface 39 40try: 41 from subprocess import getstatusoutput 42except ImportError: 43 from commands import getstatusoutput 44 45 46import re 47 48 49def get_all_modules(): 50 try: 51 all_modules = [] 52 rc, output = getstatusoutput("semodule -l 2>/dev/null") 53 if rc == 0: 54 l = output.split("\n") 55 for i in l: 56 all_modules.append(i.split()[0]) 57 except: 58 pass 59 60 return all_modules 61 62 63## 64## I18N 65## 66PROGNAME = "policycoreutils" 67try: 68 import gettext 69 kwargs = {} 70 if sys.version_info < (3,): 71 kwargs['unicode'] = True 72 gettext.install(PROGNAME, 73 localedir="/usr/share/locale", 74 codeset='utf-8', 75 **kwargs) 76except: 77 try: 78 import builtins 79 builtins.__dict__['_'] = str 80 except ImportError: 81 import __builtin__ 82 __builtin__.__dict__['_'] = unicode 83 84version = "1.0" 85 86sys.path.append('/usr/share/system-config-selinux') 87sys.path.append('.') 88 89# From John Hunter http://www.daa.com.au/pipermail/pygtk/2003-February/004454.html 90 91 92def foreach(model, path, iter, selected): 93 selected.append(model.get_value(iter, 0)) 94 95## 96## Pull in the Glade file 97## 98xml = Gtk.Builder() 99xml.set_translation_domain(PROGNAME) 100if os.access("polgen.ui", os.F_OK): 101 xml.add_from_file("polgen.ui") 102else: 103 xml.add_from_file("/usr/share/system-config-selinux/polgen.ui") 104 105FILE = 1 106DIR = 2 107 108 109class childWindow: 110 START_PAGE = 0 111 SELECT_TYPE_PAGE = 0 112 APP_PAGE = 1 113 EXISTING_USER_PAGE = 2 114 TRANSITION_PAGE = 3 115 USER_TRANSITION_PAGE = 4 116 ADMIN_PAGE = 5 117 ROLE_PAGE = 6 118 IN_NET_PAGE = 7 119 OUT_NET_PAGE = 8 120 COMMON_APPS_PAGE = 9 121 FILES_PAGE = 10 122 BOOLEAN_PAGE = 11 123 SELECT_DIR_PAGE = 12 124 FINISH_PAGE = 12 125 126 def __init__(self): 127 self.xml = xml 128 self.notebook = xml.get_object("notebook") 129 self.label_dict = {} 130 self.tooltip_dict = {} 131 label = xml.get_object("select_label") 132 self.label_dict[label] = label.get_text() 133 134 label = xml.get_object("select_user_roles_label") 135 self.label_dict[label] = label.get_text() 136 137 label = xml.get_object("select_dir_label") 138 self.label_dict[label] = label.get_text() 139 140 label = xml.get_object("select_domain_admin_label") 141 self.label_dict[label] = label.get_text() 142 143 label = xml.get_object("select_in_label") 144 self.label_dict[label] = label.get_text() 145 146 label = xml.get_object("select_out_label") 147 self.label_dict[label] = label.get_text() 148 149 label = xml.get_object("select_common_label") 150 self.label_dict[label] = label.get_text() 151 152 label = xml.get_object("select_manages_label") 153 self.label_dict[label] = label.get_text() 154 155 label = xml.get_object("select_booleans_label") 156 self.label_dict[label] = label.get_text() 157 158 label = xml.get_object("existing_user_treeview") 159 self.tooltip_dict[label] = label.get_tooltip_text() 160 161 label = xml.get_object("transition_treeview") 162 self.tooltip_dict[label] = label.get_tooltip_text() 163 164 label = xml.get_object("in_tcp_all_checkbutton") 165 self.tooltip_dict[label] = label.get_tooltip_text() 166 167 label = xml.get_object("in_tcp_reserved_checkbutton") 168 self.tooltip_dict[label] = label.get_tooltip_text() 169 170 label = xml.get_object("in_tcp_unreserved_checkbutton") 171 self.tooltip_dict[label] = label.get_tooltip_text() 172 173 label = xml.get_object("in_tcp_entry") 174 self.tooltip_dict[label] = label.get_tooltip_text() 175 176 label = xml.get_object("in_udp_all_checkbutton") 177 self.tooltip_dict[label] = label.get_tooltip_text() 178 179 label = xml.get_object("in_udp_reserved_checkbutton") 180 self.tooltip_dict[label] = label.get_tooltip_text() 181 182 label = xml.get_object("in_udp_unreserved_checkbutton") 183 self.tooltip_dict[label] = label.get_tooltip_text() 184 185 label = xml.get_object("in_udp_entry") 186 self.tooltip_dict[label] = label.get_tooltip_text() 187 188 label = xml.get_object("out_tcp_entry") 189 self.tooltip_dict[label] = label.get_tooltip_text() 190 191 label = xml.get_object("out_udp_entry") 192 self.tooltip_dict[label] = label.get_tooltip_text() 193 194 label = xml.get_object("out_tcp_all_checkbutton") 195 self.tooltip_dict[label] = label.get_tooltip_text() 196 197 label = xml.get_object("out_udp_all_checkbutton") 198 self.tooltip_dict[label] = label.get_tooltip_text() 199 200 label = xml.get_object("boolean_treeview") 201 self.tooltip_dict[label] = label.get_tooltip_text() 202 203 label = xml.get_object("write_treeview") 204 self.tooltip_dict[label] = label.get_tooltip_text() 205 206 try: 207 self.all_types = sepolicy.generate.get_all_types() 208 self.all_modules = get_all_modules() 209 self.all_roles = sepolicy.generate.get_all_roles() 210 self.all_users = sepolicy.generate.get_all_users() 211 except RuntimeError as e: 212 self.all_types = [] 213 self.all_modules = [] 214 self.all_roles = [] 215 self.all_users = [] 216 self.error(str(e)) 217 218 self.name = "" 219 handlers = { 220 "on_delete_clicked": self.delete, 221 "on_delete_boolean_clicked": self.delete_boolean, 222 "on_exec_select_clicked": self.exec_select, 223 "on_init_script_select_clicked": self.init_script_select, 224 "on_add_clicked": self.add, 225 "on_add_boolean_clicked": self.add_boolean, 226 "on_add_dir_clicked": self.add_dir, 227 "on_about_clicked": self.on_about_clicked 228 } 229 xml.connect_signals(handlers) 230 xml.get_object("cancel_button").connect("clicked", self.quit) 231 self.forward_button = xml.get_object("forward_button") 232 self.forward_button.connect("clicked", self.forward) 233 self.back_button = xml.get_object("back_button") 234 self.back_button.connect("clicked", self.back) 235 236 self.boolean_dialog = xml.get_object("boolean_dialog") 237 self.boolean_name_entry = xml.get_object("boolean_name_entry") 238 self.boolean_description_entry = xml.get_object("boolean_description_entry") 239 240 self.pages = {} 241 for i in sepolicy.generate.USERS: 242 self.pages[i] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.TRANSITION_PAGE, self.ROLE_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE] 243 self.pages[sepolicy.generate.RUSER] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.ADMIN_PAGE, self.USER_TRANSITION_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE] 244 self.pages[sepolicy.generate.LUSER] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.TRANSITION_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE] 245 self.pages[sepolicy.generate.SANDBOX] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE] 246 self.pages[sepolicy.generate.EUSER] = [self.SELECT_TYPE_PAGE, self.EXISTING_USER_PAGE, self.TRANSITION_PAGE, self.ROLE_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE] 247 248 for i in sepolicy.generate.APPLICATIONS: 249 self.pages[i] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.COMMON_APPS_PAGE, self.FILES_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE] 250 self.pages[sepolicy.generate.USER] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.USER_TRANSITION_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.COMMON_APPS_PAGE, self.FILES_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE] 251 252 self.current_page = 0 253 self.back_button.set_sensitive(0) 254 255 self.network_buttons = {} 256 257 self.in_tcp_all_checkbutton = xml.get_object("in_tcp_all_checkbutton") 258 self.in_tcp_reserved_checkbutton = xml.get_object("in_tcp_reserved_checkbutton") 259 self.in_tcp_unreserved_checkbutton = xml.get_object("in_tcp_unreserved_checkbutton") 260 self.in_tcp_entry = self.xml.get_object("in_tcp_entry") 261 self.network_buttons[self.in_tcp_all_checkbutton] = [self.in_tcp_reserved_checkbutton, self.in_tcp_unreserved_checkbutton, self.in_tcp_entry] 262 263 self.out_tcp_all_checkbutton = xml.get_object("out_tcp_all_checkbutton") 264 self.out_tcp_reserved_checkbutton = xml.get_object("out_tcp_reserved_checkbutton") 265 self.out_tcp_unreserved_checkbutton = xml.get_object("out_tcp_unreserved_checkbutton") 266 self.out_tcp_entry = self.xml.get_object("out_tcp_entry") 267 268 self.network_buttons[self.out_tcp_all_checkbutton] = [self.out_tcp_entry] 269 270 self.in_udp_all_checkbutton = xml.get_object("in_udp_all_checkbutton") 271 self.in_udp_reserved_checkbutton = xml.get_object("in_udp_reserved_checkbutton") 272 self.in_udp_unreserved_checkbutton = xml.get_object("in_udp_unreserved_checkbutton") 273 self.in_udp_entry = self.xml.get_object("in_udp_entry") 274 275 self.network_buttons[self.in_udp_all_checkbutton] = [self.in_udp_reserved_checkbutton, self.in_udp_unreserved_checkbutton, self.in_udp_entry] 276 277 self.out_udp_all_checkbutton = xml.get_object("out_udp_all_checkbutton") 278 self.out_udp_entry = self.xml.get_object("out_udp_entry") 279 self.network_buttons[self.out_udp_all_checkbutton] = [self.out_udp_entry] 280 281 for b in self.network_buttons.keys(): 282 b.connect("clicked", self.network_all_clicked) 283 284 self.boolean_treeview = self.xml.get_object("boolean_treeview") 285 self.boolean_store = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) 286 self.boolean_treeview.set_model(self.boolean_store) 287 self.boolean_store.set_sort_column_id(0, Gtk.SortType.ASCENDING) 288 col = Gtk.TreeViewColumn(_("Name"), Gtk.CellRendererText(), text=0) 289 self.boolean_treeview.append_column(col) 290 col = Gtk.TreeViewColumn(_("Description"), Gtk.CellRendererText(), text=1) 291 self.boolean_treeview.append_column(col) 292 293 self.role_treeview = self.xml.get_object("role_treeview") 294 self.role_store = Gtk.ListStore(GObject.TYPE_STRING) 295 self.role_treeview.set_model(self.role_store) 296 self.role_treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) 297 self.role_store.set_sort_column_id(0, Gtk.SortType.ASCENDING) 298 col = Gtk.TreeViewColumn(_("Role"), Gtk.CellRendererText(), text=0) 299 self.role_treeview.append_column(col) 300 301 self.existing_user_treeview = self.xml.get_object("existing_user_treeview") 302 self.existing_user_store = Gtk.ListStore(GObject.TYPE_STRING) 303 self.existing_user_treeview.set_model(self.existing_user_store) 304 self.existing_user_store.set_sort_column_id(0, Gtk.SortType.ASCENDING) 305 col = Gtk.TreeViewColumn(_("Existing_User"), Gtk.CellRendererText(), text=0) 306 self.existing_user_treeview.append_column(col) 307 308 for i in self.all_roles: 309 iter = self.role_store.append() 310 self.role_store.set_value(iter, 0, i[:-2]) 311 312 self.in_tcp_reserved_checkbutton = xml.get_object("in_tcp_reserved_checkbutton") 313 314 self.transition_treeview = self.xml.get_object("transition_treeview") 315 self.transition_store = Gtk.ListStore(GObject.TYPE_STRING) 316 self.transition_treeview.set_model(self.transition_store) 317 self.transition_treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) 318 self.transition_store.set_sort_column_id(0, Gtk.SortType.ASCENDING) 319 col = Gtk.TreeViewColumn(_("Application"), Gtk.CellRendererText(), text=0) 320 self.transition_treeview.append_column(col) 321 322 self.user_transition_treeview = self.xml.get_object("user_transition_treeview") 323 self.user_transition_store = Gtk.ListStore(GObject.TYPE_STRING) 324 self.user_transition_treeview.set_model(self.user_transition_store) 325 self.user_transition_treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) 326 self.user_transition_store.set_sort_column_id(0, Gtk.SortType.ASCENDING) 327 col = Gtk.TreeViewColumn(_("Application"), Gtk.CellRendererText(), text=0) 328 self.user_transition_treeview.append_column(col) 329 330 for i in self.all_users: 331 iter = self.user_transition_store.append() 332 self.user_transition_store.set_value(iter, 0, i[:-2]) 333 iter = self.existing_user_store.append() 334 self.existing_user_store.set_value(iter, 0, i[:-2]) 335 336 self.admin_treeview = self.xml.get_object("admin_treeview") 337 self.admin_store = Gtk.ListStore(GObject.TYPE_STRING) 338 self.admin_treeview.set_model(self.admin_store) 339 self.admin_treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) 340 self.admin_store.set_sort_column_id(0, Gtk.SortType.ASCENDING) 341 col = Gtk.TreeViewColumn(_("Application"), Gtk.CellRendererText(), text=0) 342 self.admin_treeview.append_column(col) 343 344 try: 345 for u in sepolicy.interface.get_user(): 346 iter = self.transition_store.append() 347 self.transition_store.set_value(iter, 0, u) 348 349 for a in sepolicy.interface.get_admin(): 350 iter = self.admin_store.append() 351 self.admin_store.set_value(iter, 0, a) 352 except ValueError as e: 353 self.error(e.message) 354 355 def confine_application(self): 356 return self.get_type() in sepolicy.generate.APPLICATIONS 357 358 def forward(self, arg): 359 type = self.get_type() 360 if self.current_page == self.START_PAGE: 361 self.back_button.set_sensitive(1) 362 363 if self.pages[type][self.current_page] == self.SELECT_TYPE_PAGE: 364 if self.on_select_type_page_next(): 365 return 366 367 if self.pages[type][self.current_page] == self.IN_NET_PAGE: 368 if self.on_in_net_page_next(): 369 return 370 371 if self.pages[type][self.current_page] == self.OUT_NET_PAGE: 372 if self.on_out_net_page_next(): 373 return 374 375 if self.pages[type][self.current_page] == self.APP_PAGE: 376 if self.on_name_page_next(): 377 return 378 379 if self.pages[type][self.current_page] == self.EXISTING_USER_PAGE: 380 if self.on_existing_user_page_next(): 381 return 382 383 if self.pages[type][self.current_page] == self.SELECT_DIR_PAGE: 384 outputdir = self.output_entry.get_text() 385 if not os.path.isdir(outputdir): 386 self.error(_("%s must be a directory") % outputdir) 387 return False 388 389 if self.pages[type][self.current_page] == self.FINISH_PAGE: 390 self.generate_policy() 391 self.xml.get_object("cancel_button").set_label(Gtk.STOCK_CLOSE) 392 else: 393 self.current_page = self.current_page + 1 394 self.notebook.set_current_page(self.pages[type][self.current_page]) 395 if self.pages[type][self.current_page] == self.FINISH_PAGE: 396 self.forward_button.set_label(Gtk.STOCK_APPLY) 397 398 def back(self, arg): 399 type = self.get_type() 400 if self.pages[type][self.current_page] == self.FINISH_PAGE: 401 self.forward_button.set_label(Gtk.STOCK_GO_FORWARD) 402 403 self.current_page = self.current_page - 1 404 self.notebook.set_current_page(self.pages[type][self.current_page]) 405 if self.pages[type][self.current_page] == self.START_PAGE: 406 self.back_button.set_sensitive(0) 407 408 def network_all_clicked(self, button): 409 active = button.get_active() 410 for b in self.network_buttons[button]: 411 b.set_sensitive(not active) 412 413 def verify(self, message, title=""): 414 dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO, 415 Gtk.ButtonsType.YES_NO, 416 message) 417 dlg.set_title(title) 418 dlg.set_position(Gtk.WindowPosition.MOUSE) 419 dlg.show_all() 420 rc = dlg.run() 421 dlg.destroy() 422 return rc 423 424 def info(self, message): 425 dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO, 426 Gtk.ButtonsType.OK, 427 message) 428 dlg.set_position(Gtk.WindowPosition.MOUSE) 429 dlg.show_all() 430 dlg.run() 431 dlg.destroy() 432 433 def error(self, message): 434 dlg = Gtk.MessageDialog(None, 0, Gtk.MessageType.ERROR, 435 Gtk.ButtonsType.CLOSE, 436 message) 437 dlg.set_position(Gtk.WindowPosition.MOUSE) 438 dlg.show_all() 439 dlg.run() 440 dlg.destroy() 441 442 def get_name(self): 443 if self.existing_user_radiobutton.get_active(): 444 store, iter = self.existing_user_treeview.get_selection().get_selected() 445 if iter == None: 446 raise ValueError(_("You must select a user")) 447 return store.get_value(iter, 0) 448 else: 449 return self.name_entry.get_text() 450 451 def get_type(self): 452 if self.sandbox_radiobutton.get_active(): 453 return sepolicy.generate.SANDBOX 454 if self.cgi_radiobutton.get_active(): 455 return sepolicy.generate.CGI 456 if self.user_radiobutton.get_active(): 457 return sepolicy.generate.USER 458 if self.init_radiobutton.get_active(): 459 return sepolicy.generate.DAEMON 460 if self.dbus_radiobutton.get_active(): 461 return sepolicy.generate.DBUS 462 if self.inetd_radiobutton.get_active(): 463 return sepolicy.generate.INETD 464 if self.login_user_radiobutton.get_active(): 465 return sepolicy.generate.LUSER 466 if self.admin_user_radiobutton.get_active(): 467 return sepolicy.generate.AUSER 468 if self.xwindows_user_radiobutton.get_active(): 469 return sepolicy.generate.XUSER 470 if self.terminal_user_radiobutton.get_active(): 471 return sepolicy.generate.TUSER 472 if self.root_user_radiobutton.get_active(): 473 return sepolicy.generate.RUSER 474 if self.existing_user_radiobutton.get_active(): 475 return sepolicy.generate.EUSER 476 477 def generate_policy(self, *args): 478 outputdir = self.output_entry.get_text() 479 try: 480 my_policy = sepolicy.generate.policy(self.get_name(), self.get_type()) 481 482 iter = self.boolean_store.get_iter_first() 483 while(iter): 484 my_policy.add_boolean(self.boolean_store.get_value(iter, 0), self.boolean_store.get_value(iter, 1)) 485 iter = self.boolean_store.iter_next(iter) 486 487 if self.get_type() in sepolicy.generate.APPLICATIONS: 488 my_policy.set_program(self.exec_entry.get_text()) 489 my_policy.gen_symbols() 490 491 my_policy.set_use_syslog(self.syslog_checkbutton.get_active() == 1) 492 my_policy.set_use_tmp(self.tmp_checkbutton.get_active() == 1) 493 my_policy.set_use_uid(self.uid_checkbutton.get_active() == 1) 494 my_policy.set_use_pam(self.pam_checkbutton.get_active() == 1) 495 496 my_policy.set_use_dbus(self.dbus_checkbutton.get_active() == 1) 497 my_policy.set_use_audit(self.audit_checkbutton.get_active() == 1) 498 my_policy.set_use_terminal(self.terminal_checkbutton.get_active() == 1) 499 my_policy.set_use_mail(self.mail_checkbutton.get_active() == 1) 500 if self.get_type() is sepolicy.generate.DAEMON: 501 my_policy.set_init_script(self.init_script_entry.get_text()) 502 if self.get_type() == sepolicy.generate.USER: 503 selected = [] 504 self.user_transition_treeview.get_selection().selected_foreach(foreach, selected) 505 my_policy.set_transition_users(selected) 506 else: 507 if self.get_type() == sepolicy.generate.RUSER: 508 selected = [] 509 self.admin_treeview.get_selection().selected_foreach(foreach, selected) 510 my_policy.set_admin_domains(selected) 511 selected = [] 512 self.user_transition_treeview.get_selection().selected_foreach(foreach, selected) 513 my_policy.set_transition_users(selected) 514 else: 515 selected = [] 516 self.transition_treeview.get_selection().selected_foreach(foreach, selected) 517 my_policy.set_transition_domains(selected) 518 519 selected = [] 520 self.role_treeview.get_selection().selected_foreach(foreach, selected) 521 my_policy.set_admin_roles(selected) 522 523 my_policy.set_in_tcp(self.in_tcp_all_checkbutton.get_active(), self.in_tcp_reserved_checkbutton.get_active(), self.in_tcp_unreserved_checkbutton.get_active(), self.in_tcp_entry.get_text()) 524 my_policy.set_in_udp(self.in_udp_all_checkbutton.get_active(), self.in_udp_reserved_checkbutton.get_active(), self.in_udp_unreserved_checkbutton.get_active(), self.in_udp_entry.get_text()) 525 my_policy.set_out_tcp(self.out_tcp_all_checkbutton.get_active(), self.out_tcp_entry.get_text()) 526 my_policy.set_out_udp(self.out_udp_all_checkbutton.get_active(), self.out_udp_entry.get_text()) 527 528 iter = self.store.get_iter_first() 529 while(iter): 530 if self.store.get_value(iter, 1) == FILE: 531 my_policy.add_file(self.store.get_value(iter, 0)) 532 else: 533 my_policy.add_dir(self.store.get_value(iter, 0)) 534 iter = self.store.iter_next(iter) 535 536 self.info(my_policy.generate(outputdir)) 537 return False 538 except ValueError as e: 539 self.error(e.message) 540 541 def delete(self, args): 542 store, iter = self.view.get_selection().get_selected() 543 if iter != None: 544 store.remove(iter) 545 self.view.get_selection().select_path((0,)) 546 547 def delete_boolean(self, args): 548 store, iter = self.boolean_treeview.get_selection().get_selected() 549 if iter != None: 550 store.remove(iter) 551 self.boolean_treeview.get_selection().select_path((0,)) 552 553 def add_boolean(self, type): 554 self.boolean_name_entry.set_text("") 555 self.boolean_description_entry.set_text("") 556 rc = self.boolean_dialog.run() 557 self.boolean_dialog.hide() 558 if rc == Gtk.ResponseType.CANCEL: 559 return 560 iter = self.boolean_store.append() 561 self.boolean_store.set_value(iter, 0, self.boolean_name_entry.get_text()) 562 self.boolean_store.set_value(iter, 1, self.boolean_description_entry.get_text()) 563 564 def __add(self, type): 565 rc = self.file_dialog.run() 566 self.file_dialog.hide() 567 if rc == Gtk.ResponseType.CANCEL: 568 return 569 for i in self.file_dialog.get_filenames(): 570 iter = self.store.append() 571 self.store.set_value(iter, 0, i) 572 self.store.set_value(iter, 1, type) 573 574 def exec_select(self, args): 575 self.file_dialog.set_select_multiple(0) 576 self.file_dialog.set_title(_("Select executable file to be confined.")) 577 self.file_dialog.set_action(Gtk.FileChooserAction.OPEN) 578 self.file_dialog.set_current_folder("/usr/sbin") 579 rc = self.file_dialog.run() 580 self.file_dialog.hide() 581 if rc == Gtk.ResponseType.CANCEL: 582 return 583 self.exec_entry.set_text(self.file_dialog.get_filename()) 584 585 def init_script_select(self, args): 586 self.file_dialog.set_select_multiple(0) 587 self.file_dialog.set_title(_("Select init script file to be confined.")) 588 self.file_dialog.set_action(Gtk.FileChooserAction.OPEN) 589 self.file_dialog.set_current_folder("/etc/rc.d/init.d") 590 rc = self.file_dialog.run() 591 self.file_dialog.hide() 592 if rc == Gtk.ResponseType.CANCEL: 593 return 594 self.init_script_entry.set_text(self.file_dialog.get_filename()) 595 596 def add(self, args): 597 self.file_dialog.set_title(_("Select file(s) that confined application creates or writes")) 598 self.file_dialog.set_current_folder("/") 599 self.file_dialog.set_action(Gtk.FileChooserAction.OPEN) 600 self.file_dialog.set_select_multiple(1) 601 self.__add(FILE) 602 603 def add_dir(self, args): 604 self.file_dialog.set_title(_("Select directory(s) that the confined application owns and writes into")) 605 self.file_dialog.set_current_folder("/") 606 self.file_dialog.set_select_multiple(1) 607 self.file_dialog.set_action(Gtk.FileChooserAction.SELECT_FOLDER) 608 self.__add(DIR) 609 610 def on_about_clicked(self, args): 611 dlg = xml.get_object("about_dialog") 612 dlg.run() 613 dlg.hide() 614 615 def quit(self, args): 616 Gtk.main_quit() 617 618 def setupScreen(self): 619 # Bring in widgets from glade file. 620 self.mainWindow = self.xml.get_object("main_window") 621 self.druid = self.xml.get_object("druid") 622 self.type = 0 623 self.name_entry = self.xml.get_object("name_entry") 624 self.name_entry.connect("insert_text", self.on_name_entry_changed) 625 self.name_entry.connect("focus_out_event", self.on_focus_out_event) 626 self.exec_entry = self.xml.get_object("exec_entry") 627 self.exec_button = self.xml.get_object("exec_button") 628 self.init_script_entry = self.xml.get_object("init_script_entry") 629 self.init_script_button = self.xml.get_object("init_script_button") 630 self.output_entry = self.xml.get_object("output_entry") 631 self.output_entry.set_text(os.getcwd()) 632 self.xml.get_object("output_button").connect("clicked", self.output_button_clicked) 633 634 self.xwindows_user_radiobutton = self.xml.get_object("xwindows_user_radiobutton") 635 self.terminal_user_radiobutton = self.xml.get_object("terminal_user_radiobutton") 636 self.root_user_radiobutton = self.xml.get_object("root_user_radiobutton") 637 self.login_user_radiobutton = self.xml.get_object("login_user_radiobutton") 638 self.admin_user_radiobutton = self.xml.get_object("admin_user_radiobutton") 639 self.existing_user_radiobutton = self.xml.get_object("existing_user_radiobutton") 640 641 self.user_radiobutton = self.xml.get_object("user_radiobutton") 642 self.init_radiobutton = self.xml.get_object("init_radiobutton") 643 self.inetd_radiobutton = self.xml.get_object("inetd_radiobutton") 644 self.dbus_radiobutton = self.xml.get_object("dbus_radiobutton") 645 self.cgi_radiobutton = self.xml.get_object("cgi_radiobutton") 646 self.sandbox_radiobutton = self.xml.get_object("sandbox_radiobutton") 647 self.tmp_checkbutton = self.xml.get_object("tmp_checkbutton") 648 self.uid_checkbutton = self.xml.get_object("uid_checkbutton") 649 self.pam_checkbutton = self.xml.get_object("pam_checkbutton") 650 self.dbus_checkbutton = self.xml.get_object("dbus_checkbutton") 651 self.audit_checkbutton = self.xml.get_object("audit_checkbutton") 652 self.terminal_checkbutton = self.xml.get_object("terminal_checkbutton") 653 self.mail_checkbutton = self.xml.get_object("mail_checkbutton") 654 self.syslog_checkbutton = self.xml.get_object("syslog_checkbutton") 655 self.view = self.xml.get_object("write_treeview") 656 self.file_dialog = self.xml.get_object("filechooserdialog") 657 658 self.store = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_INT) 659 self.view.set_model(self.store) 660 col = Gtk.TreeViewColumn("", Gtk.CellRendererText(), text=0) 661 col.set_resizable(True) 662 self.view.append_column(col) 663 self.view.get_selection().select_path((0,)) 664 665 def output_button_clicked(self, *args): 666 self.file_dialog.set_title(_("Select directory to generate policy files in")) 667 self.file_dialog.set_action(Gtk.FileChooserAction.SELECT_FOLDER) 668 self.file_dialog.set_select_multiple(0) 669 rc = self.file_dialog.run() 670 self.file_dialog.hide() 671 if rc == Gtk.ResponseType.CANCEL: 672 return 673 self.output_entry.set_text(self.file_dialog.get_filename()) 674 675 def on_name_entry_changed(self, entry, text, size, position): 676 if text.find(" ") >= 0: 677 entry.stop_emission_by_name("insert-text") 678 679 def on_focus_out_event(self, entry, third): 680 name = entry.get_text() 681 if self.name != name: 682 if name in self.all_types: 683 if self.verify(_("Type %s_t already defined in current policy.\nDo you want to continue?") % name, _("Verify Name")) == Gtk.ResponseType.NO: 684 entry.set_text("") 685 return False 686 if name in self.all_modules: 687 if self.verify(_("Module %s already loaded in current policy.\nDo you want to continue?") % name, _("Verify Name")) == Gtk.ResponseType.NO: 688 entry.set_text("") 689 return False 690 691 file = "/etc/rc.d/init.d/" + name 692 if os.path.isfile(file) and self.init_script_entry.get_text() == "": 693 self.init_script_entry.set_text(file) 694 695 file = "/usr/sbin/" + name 696 if os.path.isfile(file) and self.exec_entry.get_text() == "": 697 self.exec_entry.set_text(file) 698 699 self.name = name 700 return False 701 702 def on_in_net_page_next(self, *args): 703 try: 704 sepolicy.generate.verify_ports(self.in_tcp_entry.get_text()) 705 sepolicy.generate.verify_ports(self.in_udp_entry.get_text()) 706 except ValueError as e: 707 self.error(e.message) 708 return True 709 710 def on_out_net_page_next(self, *args): 711 try: 712 sepolicy.generate.verify_ports(self.out_tcp_entry.get_text()) 713 sepolicy.generate.verify_ports(self.out_udp_entry.get_text()) 714 except ValueError as e: 715 self.error(e.message) 716 return True 717 718 def on_select_type_page_next(self, *args): 719 self.exec_entry.set_sensitive(self.confine_application()) 720 self.exec_button.set_sensitive(self.confine_application()) 721 self.init_script_entry.set_sensitive(self.init_radiobutton.get_active()) 722 self.init_script_button.set_sensitive(self.init_radiobutton.get_active()) 723 724 def on_existing_user_page_next(self, *args): 725 store, iter = self.view.get_selection().get_selected() 726 if iter != None: 727 self.error(_("You must select a user")) 728 return True 729 730 def on_name_page_next(self, *args): 731 name = self.name_entry.get_text() 732 if not name.isalnum(): 733 self.error(_("You must add a name made up of letters and numbers and containing no spaces.")) 734 return True 735 736 for i in self.label_dict: 737 text = '<b>%s</b>' % (self.label_dict[i] % ("'" + name + "'")) 738 i.set_markup(text) 739 740 for i in self.tooltip_dict: 741 text = self.tooltip_dict[i] % ("'" + name + "'") 742 i.set_tooltip_text(text) 743 744 if self.confine_application(): 745 exe = self.exec_entry.get_text() 746 if exe == "": 747 self.error(_("You must enter a executable")) 748 return True 749 policy = sepolicy.generate.policy(name, self.get_type()) 750 policy.set_program(exe) 751 policy.gen_writeable() 752 policy.gen_symbols() 753 for f in policy.files.keys(): 754 iter = self.store.append() 755 self.store.set_value(iter, 0, f) 756 self.store.set_value(iter, 1, FILE) 757 758 for f in policy.dirs.keys(): 759 iter = self.store.append() 760 self.store.set_value(iter, 0, f) 761 self.store.set_value(iter, 1, DIR) 762 self.tmp_checkbutton.set_active(policy.use_tmp) 763 self.uid_checkbutton.set_active(policy.use_uid) 764 self.pam_checkbutton.set_active(policy.use_pam) 765 self.dbus_checkbutton.set_active(policy.use_dbus) 766 self.audit_checkbutton.set_active(policy.use_audit) 767 self.terminal_checkbutton.set_active(policy.use_terminal) 768 self.mail_checkbutton.set_active(policy.use_mail) 769 self.syslog_checkbutton.set_active(policy.use_syslog) 770 771 def stand_alone(self): 772 desktopName = _("Configue SELinux") 773 774 self.setupScreen() 775 self.mainWindow.connect("destroy", self.quit) 776 777 self.mainWindow.show_all() 778 Gtk.main() 779 780if __name__ == "__main__": 781 signal.signal(signal.SIGINT, signal.SIG_DFL) 782 783 app = childWindow() 784 app.stand_alone() 785