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