Home | History | Annotate | Download | only in sepolicy
      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