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