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