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