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 
    245 def 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 
    259 def _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 
    281 def 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 
    324 def 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 
    333 def 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 
    344 def 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 
    366 def 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 
    390 def 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 
    413 def 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 
    424 def 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 
    441 def 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 
    451 def 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 
    464 def transition(args):
    465     from sepolicy.transition import setrans
    466     mytrans = setrans(args.source, args.target)
    467     mytrans.output()
    468 
    469 
    470 def 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 
    482 def 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 
    499 def 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 
    511 def 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 
    571 def 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 
    597 def 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 
    676 if __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