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