1#!/usr/bin/python3 -EsI 2# Copyright (C) 2012 Red Hat 3# AUTHOR: Dan Walsh <[email protected]> 4# see file 'COPYING' for use and warranty information 5# 6# semanage is a tool for managing SELinux configuration files 7# 8# This program is free software; you can redistribute it and/or 9# modify it under the terms of the GNU General Public License as 10# published by the Free Software Foundation; either version 2 of 11# the License, or (at your option) any later version. 12# 13# This program is distributed in the hope that it will be useful, 14# but WITHOUT ANY WARRANTY; without even the implied warranty of 15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16# GNU General Public License for more details. 17# 18# You should have received a copy of the GNU General Public License 19# along with this program; if not, write to the Free Software 20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 21# 02111-1307 USA 22# 23# 24import os 25import sys 26import selinux 27import sepolicy 28from multiprocessing import Pool 29from sepolicy import get_os_version, get_conditionals, get_conditionals_format_text 30import argparse 31PROGNAME = "selinux-python" 32try: 33 import gettext 34 kwargs = {} 35 if sys.version_info < (3,): 36 kwargs['unicode'] = True 37 t = gettext.translation(PROGNAME, 38 localedir="/usr/share/locale", 39 **kwargs, 40 fallback=True) 41 _ = t.gettext 42except: 43 try: 44 import builtins 45 builtins.__dict__['_'] = str 46 except ImportError: 47 import __builtin__ 48 __builtin__.__dict__['_'] = unicode 49 50usage = "sepolicy generate [-h] [-n NAME] [-p PATH] [" 51usage_dict = {' --newtype': ('-t [TYPES [TYPES ...]]',), ' --customize': ('-d DOMAIN', '-a ADMIN_DOMAIN', "[ -w WRITEPATHS ]",), ' --admin_user': ('[-r TRANSITION_ROLE ]', "[ -w WRITEPATHS ]",), ' --application': ('COMMAND', "[ -w WRITEPATHS ]",), ' --cgi': ('COMMAND', "[ -w WRITEPATHS ]",), ' --confined_admin': ('-a ADMIN_DOMAIN', "[ -w WRITEPATHS ]",), ' --dbus': ('COMMAND', "[ -w WRITEPATHS ]",), ' --desktop_user': ('', "[ -w WRITEPATHS ]",), ' --inetd': ('COMMAND', "[ -w WRITEPATHS ]",), ' --init': ('COMMAND', "[ -w WRITEPATHS ]",), ' --sandbox': ("[ -w WRITEPATHS ]",), ' --term_user': ("[ -w WRITEPATHS ]",), ' --x_user': ("[ -w WRITEPATHS ]",)} 52 53 54class CheckPath(argparse.Action): 55 56 def __call__(self, parser, namespace, values, option_string=None): 57 if not os.path.exists(values): 58 raise ValueError("%s does not exist" % values) 59 setattr(namespace, self.dest, values) 60 61 62class CheckType(argparse.Action): 63 64 def __call__(self, parser, namespace, values, option_string=None): 65 if isinstance(values, str): 66 setattr(namespace, self.dest, values) 67 else: 68 newval = getattr(namespace, self.dest) 69 if not newval: 70 newval = [] 71 72 for v in values: 73 newval.append(v) 74 setattr(namespace, self.dest, newval) 75 76 77class CheckBoolean(argparse.Action): 78 79 def __call__(self, parser, namespace, values, option_string=None): 80 booleans = sepolicy.get_all_booleans() 81 newval = getattr(namespace, self.dest) 82 if not newval: 83 newval = [] 84 85 if isinstance(values, str): 86 v = selinux.selinux_boolean_sub(values) 87 if v not in booleans: 88 raise ValueError("%s must be an SELinux process domain:\nValid domains: %s" % (v, ", ".join(booleans))) 89 newval.append(v) 90 setattr(namespace, self.dest, newval) 91 else: 92 for value in values: 93 v = selinux.selinux_boolean_sub(value) 94 if v not in booleans: 95 raise ValueError("%s must be an SELinux boolean:\nValid boolean: %s" % (v, ", ".join(booleans))) 96 newval.append(v) 97 setattr(namespace, self.dest, newval) 98 99 100class CheckDomain(argparse.Action): 101 102 def __call__(self, parser, namespace, values, option_string=None): 103 domains = sepolicy.get_all_domains() 104 105 if isinstance(values, str): 106 values = sepolicy.get_real_type_name(values) 107 if values not in domains: 108 raise ValueError("%s must be an SELinux process domain:\nValid domains: %s" % (values, ", ".join(domains))) 109 setattr(namespace, self.dest, values) 110 else: 111 newval = getattr(namespace, self.dest) 112 if not newval: 113 newval = [] 114 115 for v in values: 116 v = sepolicy.get_real_type_name(v) 117 if v not in domains: 118 raise ValueError("%s must be an SELinux process domain:\nValid domains: %s" % (v, ", ".join(domains))) 119 newval.append(v) 120 setattr(namespace, self.dest, newval) 121 122all_classes = None 123 124 125class CheckClass(argparse.Action): 126 127 def __call__(self, parser, namespace, values, option_string=None): 128 global all_classes 129 if not all_classes: 130 all_classes = map(lambda x: x['name'], sepolicy.info(sepolicy.TCLASS)) 131 if values not in all_classes: 132 raise ValueError("%s must be an SELinux class:\nValid classes: %s" % (values, ", ".join(all_classes))) 133 134 setattr(namespace, self.dest, values) 135 136 137class CheckAdmin(argparse.Action): 138 139 def __call__(self, parser, namespace, values, option_string=None): 140 from sepolicy.interface import get_admin 141 newval = getattr(namespace, self.dest) 142 if not newval: 143 newval = [] 144 admins = get_admin() 145 if values not in admins: 146 raise ValueError("%s must be an SELinux admin domain:\nValid admin domains: %s" % (values, ", ".join(admins))) 147 newval.append(values) 148 setattr(namespace, self.dest, newval) 149 150 151class CheckPort(argparse.Action): 152 153 def __call__(self, parser, namespace, values, option_string=None): 154 newval = getattr(namespace, self.dest) 155 if not newval: 156 newval = [] 157 for v in values: 158 if v < 1 or v > 65536: 159 raise ValueError("%s must be an integer between 1 and 65536" % v) 160 newval.append(v) 161 setattr(namespace, self.dest, newval) 162 163 164class CheckPortType(argparse.Action): 165 166 def __call__(self, parser, namespace, values, option_string=None): 167 port_types = sepolicy.get_all_port_types() 168 newval = getattr(namespace, self.dest) 169 if not newval: 170 newval = [] 171 for v in values: 172 v = sepolicy.get_real_type_name(v) 173 if v not in port_types: 174 raise ValueError("%s must be an SELinux port type:\nValid port types: %s" % (v, ", ".join(port_types))) 175 newval.append(v) 176 setattr(namespace, self.dest, newval) 177 178 179class LoadPolicy(argparse.Action): 180 181 def __call__(self, parser, namespace, values, option_string=None): 182 import sepolicy 183 sepolicy.policy(values) 184 setattr(namespace, self.dest, values) 185 186 187class CheckUser(argparse.Action): 188 189 def __call__(self, parser, namespace, value, option_string=None): 190 newval = getattr(namespace, self.dest) 191 if not newval: 192 newval = [] 193 users = sepolicy.get_all_users() 194 if value not in users: 195 raise ValueError("%s must be an SELinux user:\nValid users: %s" % (value, ", ".join(users))) 196 newval.append(value) 197 setattr(namespace, self.dest, newval) 198 199 200class CheckRole(argparse.Action): 201 202 def __call__(self, parser, namespace, value, option_string=None): 203 newval = getattr(namespace, self.dest) 204 if not newval: 205 newval = [] 206 roles = sepolicy.get_all_roles() 207 if value not in roles: 208 raise ValueError("%s must be an SELinux role:\nValid roles: %s" % (value, ", ".join(roles))) 209 newval.append(value[:-2]) 210 setattr(namespace, self.dest, newval) 211 212 213class InterfaceInfo(argparse.Action): 214 215 def __call__(self, parser, namespace, values, option_string=None): 216 from sepolicy.interface import get_interface_dict 217 interface_dict = get_interface_dict() 218 for v in values: 219 if v not in interface_dict.keys(): 220 raise ValueError(_("Interface %s does not exist.") % v) 221 222 setattr(namespace, self.dest, values) 223 224 225def generate_custom_usage(usage_text, usage_dict): 226 sorted_keys = [] 227 for i in usage_dict.keys(): 228 sorted_keys.append(i) 229 sorted_keys.sort() 230 for k in sorted_keys: 231 usage_text += "%s %s |" % (k, (" ".join(usage_dict[k]))) 232 usage_text = usage_text[:-1] + "]" 233 usage_text = _(usage_text) 234 235 return usage_text 236 237# expects formats: 238# "22 (sshd_t)", "80, 8080 (httpd_t)", "all ports (port_type)" 239def port_string_to_num(val): 240 try: 241 return int(val.split(" ")[0].split(",")[0].split("-")[0]) 242 except: 243 return 99999999 244 245 246def _print_net(src, protocol, perm): 247 import sepolicy.network 248 portdict = sepolicy.network.get_network_connect(src, protocol, perm) 249 if len(portdict) > 0: 250 bold_start = "\033[1m" 251 bold_end = "\033[0;0m" 252 print("\n" + bold_start + "%s: %s %s" % (src, protocol, perm) + bold_end) 253 port_strings = [] 254 boolean_text = "" 255 for p in portdict: 256 for t, recs in portdict[p]: 257 cond = get_conditionals(src, t, "%s_socket" % protocol, [perm]) 258 if cond: 259 boolean_text = get_conditionals_format_text(cond) 260 port_strings.append("%s (%s) %s" % (", ".join(recs), t, boolean_text)) 261 else: 262 port_strings.append("%s (%s)" % (", ".join(recs), t)) 263 port_strings.sort(key=lambda param: port_string_to_num(param)) 264 for p in port_strings: 265 print("\t" + p) 266 267 268def network(args): 269 portrecs, portrecsbynum = sepolicy.gen_port_dict() 270 all_ports = [] 271 if args.list_ports: 272 for i in portrecs: 273 if i[0] not in all_ports: 274 all_ports.append(i[0]) 275 all_ports.sort() 276 print("\n".join(all_ports)) 277 278 for port in args.port: 279 found = False 280 for i in portrecsbynum: 281 if i[0] <= port and port <= i[1]: 282 if i[0] == i[1]: 283 range = i[0] 284 else: 285 range = "%s-%s" % (i[0], i[1]) 286 found = True 287 print("%d: %s %s %s" % (port, i[2], portrecsbynum[i][0], range)) 288 if not found: 289 if port < 500: 290 print("Undefined reserved port type") 291 else: 292 print("Undefined port type") 293 294 for t in args.type: 295 if (t, 'tcp') in portrecs.keys(): 296 print("%s: tcp: %s" % (t, ",".join(portrecs[t, 'tcp']))) 297 if (t, 'udp') in portrecs.keys(): 298 print( "%s: udp: %s" % (t, ",".join(portrecs[t, 'udp']))) 299 300 for a in args.applications: 301 d = sepolicy.get_init_transtype(a) 302 if d: 303 args.domain.append(d) 304 305 for d in args.domain: 306 _print_net(d, "tcp", "name_connect") 307 for net in ("tcp", "udp"): 308 _print_net(d, net, "name_bind") 309 310 311def gui_run(args): 312 try: 313 import sepolicy.gui 314 sepolicy.gui.SELinuxGui(args.domain, args.test) 315 pass 316 except ImportError: 317 raise ValueError(_("You need to install policycoreutils-gui package to use the gui option")) 318 319 320def gen_gui_args(parser): 321 gui = parser.add_parser("gui", 322 help=_('Graphical User Interface for SELinux Policy')) 323 gui.add_argument("-d", "--domain", default=None, 324 action=CheckDomain, 325 help=_("Domain name(s) of man pages to be created")) 326 gui.add_argument("-t", "--test", default=False, action="store_true", 327 help=argparse.SUPPRESS) 328 gui.set_defaults(func=gui_run) 329 330 331def manpage_work(domain, path, root, source_files, web): 332 from sepolicy.manpage import ManPage 333 m = ManPage(domain, path, root, source_files, web) 334 print(m.get_man_page_path()) 335 return (m.manpage_domains, m.manpage_roles) 336 337def manpage(args): 338 from sepolicy.manpage import HTMLManPages, gen_domains 339 340 path = args.path 341 if not args.policy and args.root != "/": 342 sepolicy.policy(sepolicy.get_installed_policy(args.root)) 343 if args.source_files and args.root == "/": 344 raise ValueError(_("Alternative root needs to be setup")) 345 346 if args.all: 347 test_domains = gen_domains() 348 else: 349 test_domains = args.domain 350 351 manpage_domains = set() 352 manpage_roles = set() 353 p = Pool() 354 async_results = [] 355 for domain in test_domains: 356 async_results.append(p.apply_async(manpage_work, [domain, path, args.root, args.source_files, args.web])) 357 for result in async_results: 358 domains, roles = result.get() 359 manpage_domains.update(domains) 360 manpage_roles.update(roles) 361 362 p.close() 363 p.join() 364 365 if args.web: 366 HTMLManPages(manpage_roles, manpage_domains, path, args.os) 367 368 369def gen_manpage_args(parser): 370 man = parser.add_parser("manpage", 371 help=_('Generate SELinux man pages')) 372 373 man.add_argument("-p", "--path", dest="path", default="/tmp", 374 help=_("path in which the generated SELinux man pages will be stored")) 375 man.add_argument("-o", "--os", dest="os", default=get_os_version(), 376 help=_("name of the OS for man pages")) 377 man.add_argument("-w", "--web", dest="web", default=False, action="store_true", 378 help=_("Generate HTML man pages structure for selected SELinux man page")) 379 man.add_argument("-r", "--root", dest="root", default="/", 380 help=_("Alternate root directory, defaults to /")) 381 man.add_argument("--source_files", dest="source_files", default=False, action="store_true", 382 help=_("With this flag, alternative root path needs to include file context files and policy.xml file")) 383 group = man.add_mutually_exclusive_group(required=True) 384 group.add_argument("-a", "--all", dest="all", default=False, 385 action="store_true", 386 help=_("All domains")) 387 group.add_argument("-d", "--domain", nargs="+", 388 action=CheckDomain, 389 help=_("Domain name(s) of man pages to be created")) 390 man.set_defaults(func=manpage) 391 392 393def gen_network_args(parser): 394 net = parser.add_parser("network", 395 help=_('Query SELinux policy network information')) 396 397 group = net.add_mutually_exclusive_group(required=True) 398 group.add_argument("-l", "--list", dest="list_ports", 399 action="store_true", 400 help=_("list all SELinux port types")) 401 group.add_argument("-p", "--port", dest="port", default=[], 402 action=CheckPort, nargs="+", type=int, 403 help=_("show SELinux type related to the port")) 404 group.add_argument("-t", "--type", dest="type", default=[], 405 action=CheckPortType, nargs="+", 406 help=_("Show ports defined for this SELinux type")) 407 group.add_argument("-d", "--domain", dest="domain", default=[], 408 action=CheckDomain, nargs="+", 409 help=_("show ports to which this domain can bind and/or connect")) 410 group.add_argument("-a", "--application", dest="applications", default=[], 411 nargs="+", 412 help=_("show ports to which this application can bind and/or connect")) 413 net.set_defaults(func=network) 414 415 416def communicate(args): 417 from sepolicy.communicate import get_types 418 419 writable = get_types(args.source, args.tclass, args.sourceaccess.split(",")) 420 readable = get_types(args.target, args.tclass, args.targetaccess.split(",")) 421 out = list(set(writable) & set(readable)) 422 423 for t in out: 424 print(t) 425 426 427def gen_communicate_args(parser): 428 comm = parser.add_parser("communicate", 429 help=_('query SELinux policy to see if domains can communicate with each other')) 430 comm.add_argument("-s", "--source", dest="source", 431 action=CheckDomain, required=True, 432 help=_("Source Domain")) 433 comm.add_argument("-t", "--target", dest="target", 434 action=CheckDomain, required=True, 435 help=_("Target Domain")) 436 comm.add_argument("-c", "--class", required=False, dest="tclass", 437 action=CheckClass, 438 default="file", help="class to use for communications, Default 'file'") 439 comm.add_argument("-S", "--sourceaccess", required=False, dest="sourceaccess", default="open,write", help="comma separate list of permissions for the source type to use, Default 'open,write'") 440 comm.add_argument("-T", "--targetaccess", required=False, dest="targetaccess", default="open,read", help="comma separated list of permissions for the target type to use, Default 'open,read'") 441 comm.set_defaults(func=communicate) 442 443 444def booleans(args): 445 from sepolicy import boolean_desc 446 if args.all: 447 rc, args.booleans = selinux.security_get_boolean_names() 448 args.booleans.sort() 449 450 for b in args.booleans: 451 print("%s=_(\"%s\")" % (b, boolean_desc(b))) 452 453 454def gen_booleans_args(parser): 455 bools = parser.add_parser("booleans", 456 help=_('query SELinux Policy to see description of booleans')) 457 group = bools.add_mutually_exclusive_group(required=True) 458 group.add_argument("-a", "--all", dest="all", default=False, 459 action="store_true", 460 help=_("get all booleans descriptions")) 461 group.add_argument("-b", "--boolean", dest="booleans", nargs="+", 462 action=CheckBoolean, required=False, 463 help=_("boolean to get description")) 464 bools.set_defaults(func=booleans) 465 466 467def transition(args): 468 from sepolicy.transition import setrans 469 mytrans = setrans(args.source, args.target) 470 mytrans.output() 471 472 473def gen_transition_args(parser): 474 trans = parser.add_parser("transition", 475 help=_('query SELinux Policy to see how a source process domain can transition to the target process domain')) 476 trans.add_argument("-s", "--source", dest="source", 477 action=CheckDomain, required=True, 478 help=_("source process domain")) 479 trans.add_argument("-t", "--target", dest="target", 480 action=CheckDomain, 481 help=_("target process domain")) 482 trans.set_defaults(func=transition) 483 484 485def print_interfaces(interfaces, args, append=""): 486 from sepolicy.interface import get_interface_format_text, interface_compile_test 487 for i in interfaces: 488 if args.verbose: 489 try: 490 print(get_interface_format_text(i + append)) 491 except KeyError: 492 print(i) 493 if args.compile: 494 try: 495 interface_compile_test(i) 496 except KeyError: 497 print(i) 498 else: 499 print(i) 500 501 502def interface(args): 503 from sepolicy.interface import get_admin, get_user, get_interface_dict, get_all_interfaces 504 if args.list_admin: 505 print_interfaces(get_admin(args.file), args, "_admin") 506 if args.list_user: 507 print_interfaces(get_user(args.file), args, "_role") 508 if args.list: 509 print_interfaces(get_all_interfaces(args.file), args) 510 if args.interfaces: 511 print_interfaces(args.interfaces, args) 512 513 514def generate(args): 515 from sepolicy.generate import policy, AUSER, RUSER, EUSER, USERS, SANDBOX, APPLICATIONS, NEWTYPE 516 cmd = None 517# numbers present POLTYPE defined in sepolicy.generate 518 conflict_args = {'TYPES': (NEWTYPE,), 'DOMAIN': (EUSER,), 'ADMIN_DOMAIN': (AUSER, RUSER, EUSER,)} 519 error_text = "" 520 521 if args.policytype is None: 522 generate_usage = generate_custom_usage(usage, usage_dict) 523 for k in usage_dict: 524 error_text += "%s" % (k) 525 print(generate_usage) 526 print(_("sepolicy generate: error: one of the arguments %s is required") % error_text) 527 sys.exit(1) 528 529 if args.policytype in APPLICATIONS: 530 if not args.command: 531 raise ValueError(_("Command required for this type of policy")) 532 cmd = os.path.realpath(args.command) 533 if not args.name: 534 args.name = os.path.basename(cmd).replace("-", "_") 535 536 mypolicy = policy(args.name, args.policytype) 537 if cmd: 538 mypolicy.set_program(cmd) 539 540 if args.types: 541 if args.policytype not in conflict_args['TYPES']: 542 raise ValueError(_("-t option can not be used with '%s' domains. Read usage for more details.") % sepolicy.generate.poltype[args.policytype]) 543 mypolicy.set_types(args.types) 544 545 if args.domain: 546 if args.policytype not in conflict_args['DOMAIN']: 547 raise ValueError(_("-d option can not be used with '%s' domains. Read usage for more details.") % sepolicy.generate.poltype[args.policytype]) 548 549 if args.admin_domain: 550 if args.policytype not in conflict_args['ADMIN_DOMAIN']: 551 raise ValueError(_("-a option can not be used with '%s' domains. Read usage for more details.") % sepolicy.generate.poltype[args.policytype]) 552 553 if len(args.writepaths) > 0 and args.policytype == NEWTYPE: 554 555 raise ValueError(_("-w option can not be used with the --newtype option")) 556 557 for p in args.writepaths: 558 if os.path.isdir(p): 559 mypolicy.add_dir(p) 560 else: 561 mypolicy.add_file(p) 562 563 mypolicy.set_transition_users(args.user) 564 mypolicy.set_admin_roles(args.role) 565 mypolicy.set_admin_domains(args.admin_domain) 566 mypolicy.set_existing_domains(args.domain) 567 568 if args.policytype in APPLICATIONS: 569 mypolicy.gen_writeable() 570 mypolicy.gen_symbols() 571 print(mypolicy.generate(args.path)) 572 573 574def gen_interface_args(parser): 575 itf = parser.add_parser("interface", 576 help=_('List SELinux Policy interfaces')) 577 itf.add_argument("-c", "--compile", dest="compile", 578 action="store_true", default=False, 579 help="Run compile test for selected interface") 580 itf.add_argument("-v", "--verbose", dest="verbose", 581 action="store_true", default=False, 582 help="Show verbose information") 583 itf.add_argument("-f", "--file", dest="file", 584 help="Interface file") 585 group = itf.add_mutually_exclusive_group(required=True) 586 group.add_argument("-a", "--list_admin", dest="list_admin", action="store_true", default=False, 587 help="List all domains with admin interface - DOMAIN_admin()") 588 group.add_argument("-u", "--list_user", dest="list_user", action="store_true", 589 default=False, 590 help="List all domains with SELinux user role interface - DOMAIN_role()") 591 group.add_argument("-l", "--list", dest="list", action="store_true", 592 default=False, 593 help="List all interfaces") 594 group.add_argument("-i", "--interfaces", nargs="+", dest="interfaces", 595 action=InterfaceInfo, 596 help=_("Enter interface names, you wish to query")) 597 itf.set_defaults(func=interface) 598 599 600def gen_generate_args(parser): 601 from sepolicy.generate import get_poltype_desc, poltype, DAEMON, DBUS, INETD, CGI, SANDBOX, USER, EUSER, TUSER, XUSER, LUSER, AUSER, RUSER, NEWTYPE 602 603 generate_usage = generate_custom_usage(usage, usage_dict) 604 605 pol = parser.add_parser("generate", usage=generate_usage, 606 help=_('Generate SELinux Policy module template')) 607 pol.add_argument("-d", "--domain", dest="domain", default=[], 608 action=CheckDomain, nargs="*", 609 help=_("Enter domain type which you will be extending")) 610 pol.add_argument("-u", "--user", dest="user", default=[], 611 action=CheckUser, 612 help=_("Enter SELinux user(s) which will transition to this domain")) 613 pol.add_argument("-r", "--role", dest="role", default=[], 614 action=CheckRole, 615 help=_("Enter SELinux role(s) to which the administror domain will transition")) 616 pol.add_argument("-a", "--admin", dest="admin_domain", default=[], 617 action=CheckAdmin, 618 help=_("Enter domain(s) which this confined admin will administrate")) 619 pol.add_argument("-n", "--name", dest="name", 620 default=None, 621 help=_("name of policy to generate")) 622 pol.add_argument("-T", "--test", dest="test", default=False, action="store_true", 623 help=argparse.SUPPRESS) 624 pol.add_argument("-t", "--type", dest="types", default=[], nargs="*", 625 action=CheckType, 626 help="Enter type(s) for which you will generate new definition and rule(s)") 627 pol.add_argument("-p", "--path", dest="path", default=os.getcwd(), 628 help=_("path in which the generated policy files will be stored")) 629 pol.add_argument("-w", "--writepath", dest="writepaths", nargs="*", default=[], 630 help=_("path to which the confined processes will need to write")) 631 cmdtype = pol.add_argument_group(_("Policy types which require a command")) 632 cmdgroup = cmdtype.add_mutually_exclusive_group(required=False) 633 cmdgroup.add_argument("--application", dest="policytype", const=USER, 634 action="store_const", 635 help=_("Generate '%s' policy") % poltype[USER]) 636 cmdgroup.add_argument("--cgi", dest="policytype", const=CGI, 637 action="store_const", 638 help=_("Generate '%s' policy") % poltype[CGI]) 639 cmdgroup.add_argument("--dbus", dest="policytype", const=DBUS, 640 action="store_const", 641 help=_("Generate '%s' policy") % poltype[DBUS]) 642 cmdgroup.add_argument("--inetd", dest="policytype", const=INETD, 643 action="store_const", 644 help=_("Generate '%s' policy") % poltype[INETD]) 645 cmdgroup.add_argument("--init", dest="policytype", const=DAEMON, 646 action="store_const", default=DAEMON, 647 help=_("Generate '%s' policy") % poltype[DAEMON]) 648 649 type = pol.add_argument_group("Policy types which do not require a command") 650 group = type.add_mutually_exclusive_group(required=False) 651 group.add_argument("--admin_user", dest="policytype", const=AUSER, 652 action="store_const", 653 help=_("Generate '%s' policy") % poltype[AUSER]) 654 group.add_argument("--confined_admin", dest="policytype", const=RUSER, 655 action="store_const", 656 help=_("Generate '%s' policy") % poltype[RUSER]) 657 group.add_argument("--customize", dest="policytype", const=EUSER, 658 action="store_const", 659 help=_("Generate '%s' policy") % poltype[EUSER]) 660 group.add_argument("--desktop_user", dest="policytype", const=LUSER, 661 action="store_const", 662 help=_("Generate '%s' policy ") % poltype[LUSER]) 663 group.add_argument("--newtype", dest="policytype", const=NEWTYPE, 664 action="store_const", 665 help=_("Generate '%s' policy") % poltype[NEWTYPE]) 666 group.add_argument("--sandbox", dest="policytype", const=SANDBOX, 667 action="store_const", 668 help=_("Generate '%s' policy") % poltype[SANDBOX]) 669 group.add_argument("--term_user", dest="policytype", const=TUSER, 670 action="store_const", 671 help=_("Generate '%s' policy") % poltype[TUSER]) 672 group.add_argument("--x_user", dest="policytype", const=XUSER, 673 action="store_const", 674 help=_("Generate '%s' policy") % poltype[XUSER]) 675 pol.add_argument("command", nargs="?", default=None, 676 help=_("executable to confine")) 677 pol.set_defaults(func=generate) 678 679if __name__ == '__main__': 680 parser = argparse.ArgumentParser(description='SELinux Policy Inspection Tool') 681 subparsers = parser.add_subparsers(help=_("commands")) 682 parser.add_argument("-P", "--policy", dest="policy", 683 action=LoadPolicy, 684 default=None, help=_("Alternate SELinux policy, defaults to /sys/fs/selinux/policy")) 685 gen_booleans_args(subparsers) 686 gen_communicate_args(subparsers) 687 gen_generate_args(subparsers) 688 gen_gui_args(subparsers) 689 gen_interface_args(subparsers) 690 gen_manpage_args(subparsers) 691 gen_network_args(subparsers) 692 gen_transition_args(subparsers) 693 694 try: 695 if os.path.basename(sys.argv[0]) == "sepolgen": 696 parser_args = [ "generate" ] + sys.argv[1:] 697 elif len(sys.argv) > 1: 698 parser_args = sys.argv[1:] 699 else: 700 parser_args = ["-h"] 701 args = parser.parse_args(args=parser_args) 702 args.func(args) 703 sys.exit(0) 704 except ValueError as e: 705 sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e))) 706 sys.exit(1) 707 except IOError as e: 708 sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e))) 709 sys.exit(1) 710 except KeyboardInterrupt: 711 print("Out") 712 sys.exit(0) 713