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