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