| #!/usr/bin/python3 -Es |
| # Copyright (C) 2012-2013 Red Hat |
| # AUTHOR: Miroslav Grepl <[email protected]> |
| # AUTHOR: David Quigley <[email protected]> |
| # see file 'COPYING' for use and warranty information |
| # |
| # semanage is a tool for managing SELinux configuration files |
| # |
| # This program is free software; you can redistribute it and/or |
| # modify it under the terms of the GNU General Public License as |
| # published by the Free Software Foundation; either version 2 of |
| # the License, or (at your option) any later version. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with this program; if not, write to the Free Software |
| # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| # 02111-1307 USA |
| # |
| # |
| |
| import traceback |
| import argparse |
| import seobject |
| import sys |
| PROGNAME = "policycoreutils" |
| try: |
| import gettext |
| kwargs = {} |
| if sys.version_info < (3,): |
| kwargs['unicode'] = True |
| gettext.install(PROGNAME, |
| localedir="/usr/share/locale", |
| codeset='utf-8', |
| **kwargs) |
| except: |
| try: |
| import builtins |
| builtins.__dict__['_'] = str |
| except ImportError: |
| import __builtin__ |
| __builtin__.__dict__['_'] = unicode |
| |
| # define custom usages for selected main actions |
| usage_login = "semanage login [-h] [-n] [-N] [-S STORE] [" |
| usage_login_dict = {' --add': ('-s SEUSER', '-r RANGE', 'LOGIN',), ' --modify': ('-s SEUSER', '-r RANGE', 'LOGIN',), ' --delete': ('LOGIN',), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)} |
| |
| usage_fcontext = "semanage fcontext [-h] [-n] [-N] [-S STORE] [" |
| usage_fcontext_dict = {' --add': ('(', '-t TYPE', '-f FTYPE', '-r RANGE', '-s SEUSER', '|', '-e EQUAL', ')', 'FILE_SPEC',), ' --delete': ('(', '-t TYPE', '-f FTYPE', '|', '-e EQUAL', ')', 'FILE_SPEC',), ' --modify': ('(', '-t TYPE', '-f FTYPE', '-r RANGE', '-s SEUSER', '|', '-e EQUAL', ')', 'FILE_SPEC',), ' --list': ('[-C]',), ' --extract': ('',), ' --deleteall': ('',)} |
| |
| usage_user = "semanage user [-h] [-n] [-N] [-S STORE] [" |
| usage_user_dict = {' --add': ('(', '-L LEVEL', '-R ROLES', '-r RANGE', 'SEUSER', ')'), ' --delete': ('SEUSER',), ' --modify': ('(', '-L LEVEL', '-R ROLES', '-r RANGE', '-s SEUSER', 'SEUSER', ')'), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)} |
| |
| usage_port = "semanage port [-h] [-n] [-N] [-S STORE] [" |
| usage_port_dict = {' --add': ('-t TYPE', '-p PROTOCOL', '-r RANGE', '(', 'port_name', '|', 'port_range', ')'), ' --modify': ('-t TYPE', '-p PROTOCOL', '-r RANGE', '(', 'port_name', '|', 'port_range', ')'), ' --delete': ('-p PROTOCOL', '(', 'port_name', '|', 'port_range', ')'), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)} |
| |
| usage_ibpkey = "semanage ibpkey [-h] [-n] [-N] [-s STORE] [" |
| usage_ibpkey_dict = {' --add': ('-t TYPE', '-x SUBNET_PREFIX', '-r RANGE', '(', 'ibpkey_name', '|', 'pkey_range', ')'), ' --modify': ('-t TYPE', '-x SUBNET_PREFIX', '-r RANGE', '(', 'ibpkey_name', '|', 'pkey_range', ')'), ' --delete': ('-x SUBNET_PREFIX', '(', 'ibpkey_name', '|', 'pkey_range', ')'), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)} |
| |
| usage_ibendport = "semanage ibendport [-h] [-n] [-N] [-s STORE] [" |
| usage_ibendport_dict = {' --add': ('-t TYPE', '-z IBDEV_NAME', '-r RANGE', '(', 'port', ')'), ' --modify': ('-t TYPE', '-z IBDEV_NAME', '-r RANGE', '(', 'port', ')'), ' --delete': ('-z IBDEV_NAME', '-r RANGE', '(', 'port', ')'), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)} |
| |
| usage_node = "semanage node [-h] [-n] [-N] [-S STORE] [" |
| usage_node_dict = {' --add': ('-M NETMASK', '-p PROTOCOL', '-t TYPE', '-r RANGE', 'node'), ' --modify': ('-M NETMASK', '-p PROTOCOL', '-t TYPE', '-r RANGE', 'node'), ' --delete': ('-M NETMASK', '-p PROTOCOL', 'node'), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)} |
| |
| usage_interface = "semanage interface [-h] [-n] [-N] [-S STORE] [" |
| usage_interface_dict = {' --add': ('-t TYPE', '-r RANGE', 'interface'), ' --modify': ('-t TYPE', '-r RANGE', 'interface'), ' --delete': ('interface',), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)} |
| |
| usage_boolean = "semanage boolean [-h] [-n] [-N] [-S STORE] [" |
| usage_boolean_dict = {' --modify': ('(', '--on', '|', '--off', ')', 'boolean'), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)} |
| |
| class CheckRole(argparse.Action): |
| |
| def __call__(self, parser, namespace, value, option_string=None): |
| newval = getattr(namespace, self.dest) |
| if not newval: |
| newval = [] |
| try: |
| # sepolicy tries to load the SELinux policy and raises ValueError if it fails. |
| import sepolicy |
| roles = sepolicy.get_all_roles() |
| except ValueError: |
| roles = [] |
| for v in value.split(): |
| if v not in roles: |
| raise ValueError("%s must be an SELinux role:\nValid roles: %s" % (v, ", ".join(roles))) |
| newval.append(v) |
| setattr(namespace, self.dest, newval) |
| |
| |
| class seParser(argparse.ArgumentParser): |
| |
| def error(self, message): |
| if len(sys.argv) == 2: |
| self.print_help() |
| else: |
| self.print_usage() |
| self.exit(2, ('%s: error: %s\n') % (self.prog, message)) |
| |
| |
| class SetExportFile(argparse.Action): |
| |
| def __call__(self, parser, namespace, values, option_string=None): |
| if values: |
| if values != "-": |
| try: |
| sys.stdout = open(values, 'w') |
| except: |
| sys.stderr.write(traceback.format_exc()) |
| sys.exit(1) |
| setattr(namespace, self.dest, values) |
| |
| |
| class SetImportFile(argparse.Action): |
| |
| def __call__(self, parser, namespace, values, option_string=None): |
| if values and values != "-": |
| try: |
| sys.stdin = open(values, 'r') |
| except IOError as e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e))) |
| sys.exit(1) |
| setattr(namespace, self.dest, values) |
| |
| # define dictonary for seobject OBEJCTS |
| object_dict = { |
| 'login': seobject.loginRecords, |
| 'user': seobject.seluserRecords, |
| 'port': seobject.portRecords, |
| 'module': seobject.moduleRecords, |
| 'interface': seobject.interfaceRecords, |
| 'node': seobject.nodeRecords, |
| 'fcontext': seobject.fcontextRecords, |
| 'boolean': seobject.booleanRecords, |
| 'permissive': seobject.permissiveRecords, |
| 'dontaudit': seobject.dontauditClass, |
| 'ibpkey': seobject.ibpkeyRecords, |
| 'ibendport': seobject.ibendportRecords |
| } |
| |
| def generate_custom_usage(usage_text, usage_dict): |
| # generate custom usage from given text and dictonary |
| sorted_keys = [] |
| for i in usage_dict.keys(): |
| sorted_keys.append(i) |
| sorted_keys.sort() |
| for k in sorted_keys: |
| usage_text += "%s %s |" % (k, (" ".join(usage_dict[k]))) |
| usage_text = usage_text[:-1] + "]" |
| usage_text = _(usage_text) |
| |
| return usage_text |
| |
| |
| def handle_opts(args, dict, target_key): |
| # handle conflict and required options for given dictonary |
| # {action:[conflict_opts,require_opts]} |
| |
| # first we need to catch conflicts |
| for k in args.__dict__.keys(): |
| try: |
| if k in dict[target_key][0] and args.__dict__[k]: |
| print("%s option can not be used with --%s" % (target_key, k)) |
| sys.exit(2) |
| except KeyError: |
| continue |
| |
| for k in args.__dict__.keys(): |
| try: |
| if k in dict[target_key][1] and not args.__dict__[k]: |
| print("%s option is needed for %s" % (k, target_key)) |
| sys.exit(2) |
| except KeyError: |
| continue |
| |
| |
| def handleLogin(args): |
| # {action:[conflict_opts,require_opts]} |
| login_args = {'list': [('login', 'seuser'), ('')], 'add': [('locallist'), ('seuser', 'login')], 'modify': [('locallist'), ('login')], 'delete': [('locallist'), ('login')], 'extract': [('locallist', 'login', 'seuser'), ('')], 'deleteall': [('locallist'), ('')]} |
| |
| handle_opts(args, login_args, args.action) |
| |
| OBJECT = object_dict['login'](args) |
| |
| if args.action == "add": |
| OBJECT.add(args.login, args.seuser, args.range) |
| if args.action == "modify": |
| OBJECT.modify(args.login, args.seuser, args.range) |
| if args.action == "delete": |
| OBJECT.delete(args.login) |
| if args.action == "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action == "deleteall": |
| OBJECT.deleteall() |
| if args.action == "extract": |
| for i in OBJECT.customized(): |
| print("login %s" % (str(i))) |
| |
| |
| def parser_add_store(parser, name): |
| parser.add_argument('-S', '--store', default='', help=_("Select an alternate SELinux Policy Store to manage")) |
| |
| |
| def parser_add_priority(parser, name): |
| parser.add_argument('-P', '--priority', type=int, default=400, help=_("Select a priority for module operations")) |
| |
| |
| def parser_add_noheading(parser, name): |
| parser.add_argument('-n', '--noheading', action='store_false', default=True, help=_("Do not print heading when listing %s object types") % name) |
| |
| |
| def parser_add_noreload(parser, name): |
| parser.add_argument('-N', '--noreload', action='store_true', default=False, help=_('Do not reload policy after commit')) |
| |
| |
| def parser_add_locallist(parser, name): |
| parser.add_argument('-C', '--locallist', action='store_true', default=False, help=_("List %s local customizations") % name) |
| |
| |
| def parser_add_add(parser, name): |
| parser.add_argument('-a', '--add', dest='action', action='store_const', const='add', help=_("Add a record of the %s object type") % name) |
| |
| |
| def parser_add_type(parser, name): |
| parser.add_argument('-t', '--type', help=_('SELinux Type for the object')) |
| |
| |
| def parser_add_level(parser, name): |
| parser.add_argument('-L', '--level', default='s0', help=_('Default SELinux Level for SELinux user, s0 Default. (MLS/MCS Systems only)')) |
| |
| |
| def parser_add_range(parser, name): |
| parser.add_argument('-r', '--range', default='', |
| help=_(''' |
| MLS/MCS Security Range (MLS/MCS Systems only) |
| SELinux Range for SELinux login mapping |
| defaults to the SELinux user record range. |
| SELinux Range for SELinux user defaults to s0. |
| ''')) |
| |
| |
| def parser_add_proto(parser, name): |
| parser.add_argument('-p', '--proto', help=_(''' |
| Protocol for the specified port (tcp|udp|dccp|sctp) or internet protocol |
| version for the specified node (ipv4|ipv6). |
| ''')) |
| |
| def parser_add_subnet_prefix(parser, name): |
| parser.add_argument('-x', '--subnet_prefix', help=_(''' |
| Subnet prefix for the specified infiniband ibpkey. |
| ''')) |
| |
| def parser_add_ibdev_name(parser, name): |
| parser.add_argument('-z', '--ibdev_name', help=_(''' |
| Name for the specified infiniband end port. |
| ''')) |
| |
| def parser_add_modify(parser, name): |
| parser.add_argument('-m', '--modify', dest='action', action='store_const', const='modify', help=_("Modify a record of the %s object type") % name) |
| |
| |
| def parser_add_list(parser, name): |
| parser.add_argument('-l', '--list', dest='action', action='store_const', const='list', help=_("List records of the %s object type") % name) |
| |
| |
| def parser_add_delete(parser, name): |
| parser.add_argument('-d', '--delete', dest='action', action='store_const', const='delete', help=_("Delete a record of the %s object type") % name) |
| |
| |
| def parser_add_extract(parser, name): |
| parser.add_argument('-E', '--extract', dest='action', action='store_const', const='extract', help=_("Extract customizable commands, for use within a transaction")) |
| |
| |
| def parser_add_deleteall(parser, name): |
| parser.add_argument('-D', '--deleteall', dest='action', action='store_const', const='deleteall', help=_('Remove all %s objects local customizations') % name) |
| |
| |
| def parser_add_seuser(parser, name): |
| parser.add_argument('-s', '--seuser', default="", help=_("SELinux user name")) |
| |
| |
| def setupLoginParser(subparsers): |
| generated_usage = generate_custom_usage(usage_login, usage_login_dict) |
| loginParser = subparsers.add_parser('login', usage=generated_usage, help=_("Manage login mappings between linux users and SELinux confined users")) |
| parser_add_locallist(loginParser, "login") |
| parser_add_noheading(loginParser, "login") |
| parser_add_noreload(loginParser, "login") |
| parser_add_store(loginParser, "login") |
| parser_add_range(loginParser, "login") |
| |
| login_action = loginParser.add_mutually_exclusive_group(required=True) |
| |
| parser_add_add(login_action, "login") |
| parser_add_delete(login_action, "login") |
| parser_add_modify(login_action, "login") |
| parser_add_list(login_action, "login") |
| parser_add_extract(login_action, "login") |
| parser_add_deleteall(login_action, "login") |
| parser_add_seuser(loginParser, "login") |
| |
| loginParser.add_argument('login', nargs='?', default=None, help=_("login_name | %%groupname")) |
| |
| loginParser.set_defaults(func=handleLogin) |
| |
| |
| def handleFcontext(args): |
| fcontext_args = {'list': [('equal', 'ftype', 'seuser', 'type'), ('')], 'add': [('locallist'), ('type', 'file_spec')], 'modify': [('locallist'), ('type', 'file_spec')], 'delete': [('locallist'), ('file_spec')], 'extract': [('locallist', 'equal', 'ftype', 'seuser', 'type'), ('')], 'deleteall': [('locallist'), ('')]} |
| # we can not use mutually for equal because we can define some actions together with equal |
| fcontext_equal_args = {'equal': [('list', 'locallist', 'type', 'ftype', 'seuser', 'deleteall', 'extract'), ()]} |
| |
| if args.action and args.equal: |
| handle_opts(args, fcontext_equal_args, "equal") |
| else: |
| handle_opts(args, fcontext_args, args.action) |
| |
| OBJECT = object_dict['fcontext'](args) |
| |
| if args.action == "add": |
| if args.equal: |
| OBJECT.add_equal(args.file_spec, args.equal) |
| else: |
| OBJECT.add(args.file_spec, args.type, args.ftype, args.range, args.seuser) |
| if args.action == "modify": |
| if args.equal: |
| OBJECT.add_equal(args.file_spec, args.equal) |
| else: |
| OBJECT.modify(args.file_spec, args.type, args.ftype, args.range, args.seuser) |
| if args.action == "delete": |
| if args.equal: |
| OBJECT.delete(args.file_spec, args.equal) |
| else: |
| OBJECT.delete(args.file_spec, args.ftype) |
| if args.action == "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action == "deleteall": |
| OBJECT.deleteall() |
| if args.action == "extract": |
| for i in OBJECT.customized(): |
| print("fcontext %s" % str(i)) |
| |
| |
| def setupFcontextParser(subparsers): |
| ftype_help = ''' |
| File Type. This is used with fcontext. Requires a file type |
| as shown in the mode field by ls, e.g. use d to match only |
| directories or f to match only regular files. The following |
| file type options can be passed: |
| f (regular file),d (directory),c (character device), |
| b (block device),s (socket),l (symbolic link),p (named pipe) |
| If you do not specify a file type, the file type will default to "all files". |
| ''' |
| generate_usage = generate_custom_usage(usage_fcontext, usage_fcontext_dict) |
| fcontextParser = subparsers.add_parser('fcontext', usage=generate_usage, help=_("Manage file context mapping definitions")) |
| parser_add_locallist(fcontextParser, "fcontext") |
| parser_add_noheading(fcontextParser, "fcontext") |
| parser_add_noreload(fcontextParser, "fcontext") |
| parser_add_store(fcontextParser, "fcontext") |
| |
| fcontext_action = fcontextParser.add_mutually_exclusive_group(required=True) |
| parser_add_add(fcontext_action, "fcontext") |
| parser_add_delete(fcontext_action, "fcontext") |
| parser_add_modify(fcontext_action, "fcontext") |
| parser_add_list(fcontext_action, "fcontext") |
| parser_add_extract(fcontext_action, "fcontext") |
| parser_add_deleteall(fcontext_action, "fcontext") |
| |
| fcontextParser.add_argument('-e', '--equal', help=_('''Substitute target path with sourcepath when generating default |
| label. This is used with fcontext. Requires source and target |
| path arguments. The context labeling for the target subtree is |
| made equivalent to that defined for the source.''')) |
| fcontextParser.add_argument('-f', '--ftype', default="", choices=["a", "f", "d", "c", "b", "s", "l", "p"], help=_(ftype_help)) |
| parser_add_seuser(fcontextParser, "fcontext") |
| parser_add_type(fcontextParser, "fcontext") |
| parser_add_range(fcontextParser, "fcontext") |
| fcontextParser.add_argument('file_spec', nargs='?', default=None, help=_('file_spec')) |
| fcontextParser.set_defaults(func=handleFcontext) |
| |
| |
| def handleUser(args): |
| user_args = {'list': [('selinux_name', 'seuser', 'roles'), ('')], 'add': [('locallist'), ('roles', 'selinux_name')], 'modify': [('locallist'), ('selinux_name')], 'delete': [('locallist'), ('selinux_name')], 'extract': [('locallist', 'selinux_name', 'seuser', 'role'), ('')], 'deleteall': [('locallist'), ('')]} |
| |
| handle_opts(args, user_args, args.action) |
| |
| OBJECT = object_dict['user'](args) |
| |
| if args.action == "add": |
| OBJECT.add(args.selinux_name, args.roles, args.level, args.range, args.prefix) |
| if args.action == "modify": |
| OBJECT.modify(args.selinux_name, args.roles, args.level, args.range, args.prefix) |
| if args.action == "delete": |
| OBJECT.delete(args.selinux_name) |
| if args.action == "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action == "deleteall": |
| OBJECT.deleteall() |
| if args.action == "extract": |
| for i in OBJECT.customized(): |
| print("user %s" % str(i)) |
| |
| |
| def setupUserParser(subparsers): |
| generated_usage = generate_custom_usage(usage_user, usage_user_dict) |
| userParser = subparsers.add_parser('user', usage=generated_usage, help=_('Manage SELinux confined users (Roles and levels for an SELinux user)')) |
| parser_add_locallist(userParser, "user") |
| parser_add_noheading(userParser, "user") |
| parser_add_noreload(userParser, "user") |
| parser_add_store(userParser, "user") |
| |
| user_action = userParser.add_mutually_exclusive_group(required=True) |
| parser_add_add(user_action, "user") |
| parser_add_delete(user_action, "user") |
| parser_add_modify(user_action, "user") |
| parser_add_list(user_action, "user") |
| parser_add_extract(user_action, "user") |
| parser_add_deleteall(user_action, "user") |
| |
| parser_add_level(userParser, "user") |
| parser_add_range(userParser, "user") |
| userParser.add_argument('-R', '--roles', default=[], |
| action=CheckRole, |
| help=_(''' |
| SELinux Roles. You must enclose multiple roles within quotes, separate by spaces. Or specify -R multiple times. |
| ''')) |
| userParser.add_argument('-P', '--prefix', default="user", help=argparse.SUPPRESS) |
| userParser.add_argument('selinux_name', nargs='?', default=None, help=_('selinux_name')) |
| userParser.set_defaults(func=handleUser) |
| |
| |
| def handlePort(args): |
| port_args = {'list': [('port', 'type', 'proto'), ('')], 'add': [('locallist'), ('type', 'port', 'proto')], 'modify': [('localist'), ('port', 'proto')], 'delete': [('locallist'), ('port', 'proto')], 'extract': [('locallist', 'port', 'type', 'proto'), ('')], 'deleteall': [('locallist'), ('')]} |
| |
| handle_opts(args, port_args, args.action) |
| |
| OBJECT = object_dict['port'](args) |
| |
| if args.action == "add": |
| OBJECT.add(args.port, args.proto, args.range, args.type) |
| if args.action == "modify": |
| OBJECT.modify(args.port, args.proto, args.range, args.type) |
| if args.action == "delete": |
| OBJECT.delete(args.port, args.proto) |
| if args.action == "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action == "deleteall": |
| OBJECT.deleteall() |
| if args.action == "extract": |
| for i in OBJECT.customized(): |
| print("port %s" % str(i)) |
| |
| |
| def setupPortParser(subparsers): |
| generated_usage = generate_custom_usage(usage_port, usage_port_dict) |
| portParser = subparsers.add_parser('port', usage=generated_usage, help=_('Manage network port type definitions')) |
| parser_add_locallist(portParser, "port") |
| parser_add_noheading(portParser, "port") |
| parser_add_noreload(portParser, "port") |
| parser_add_store(portParser, "port") |
| |
| port_action = portParser.add_mutually_exclusive_group(required=True) |
| parser_add_add(port_action, "port") |
| parser_add_delete(port_action, "port") |
| parser_add_modify(port_action, "port") |
| parser_add_list(port_action, "port") |
| parser_add_extract(port_action, "port") |
| parser_add_deleteall(port_action, "port") |
| parser_add_type(portParser, "port") |
| parser_add_range(portParser, "port") |
| parser_add_proto(portParser, "port") |
| portParser.add_argument('port', nargs='?', default=None, help=_('port | port_range')) |
| portParser.set_defaults(func=handlePort) |
| |
| |
| |
| def handlePkey(args): |
| ibpkey_args = {'list': [('ibpkey', 'type', 'subnet_prefix'), ('')], 'add': [('locallist'), ('type', 'ibpkey', 'subnet_prefix')], 'modify': [('localist'), ('ibpkey', 'subnet_prefix')], 'delete': [('locallist'), ('ibpkey', 'subnet_prefix')], 'extract': [('locallist', 'ibpkey', 'type', 'subnet prefix'), ('')], 'deleteall': [('locallist'), ('')]} |
| |
| handle_opts(args, ibpkey_args, args.action) |
| |
| OBJECT = object_dict['ibpkey'](args) |
| |
| if args.action == "add": |
| OBJECT.add(args.ibpkey, args.subnet_prefix, args.range, args.type) |
| if args.action == "modify": |
| OBJECT.modify(args.ibpkey, args.subnet_prefix, args.range, args.type) |
| if args.action == "delete": |
| OBJECT.delete(args.ibpkey, args.subnet_prefix) |
| if args.action == "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action == "deleteall": |
| OBJECT.deleteall() |
| if args.action == "extract": |
| for i in OBJECT.customized(): |
| print("ibpkey %s" % str(i)) |
| |
| |
| def setupPkeyParser(subparsers): |
| generated_usage = generate_custom_usage(usage_ibpkey, usage_ibpkey_dict) |
| ibpkeyParser = subparsers.add_parser('ibpkey', usage=generated_usage, help=_('Manage infiniband ibpkey type definitions')) |
| parser_add_locallist(ibpkeyParser, "ibpkey") |
| parser_add_noheading(ibpkeyParser, "ibpkey") |
| parser_add_noreload(ibpkeyParser, "ibpkey") |
| parser_add_store(ibpkeyParser, "ibpkey") |
| |
| ibpkey_action = ibpkeyParser.add_mutually_exclusive_group(required=True) |
| parser_add_add(ibpkey_action, "ibpkey") |
| parser_add_delete(ibpkey_action, "ibpkey") |
| parser_add_modify(ibpkey_action, "ibpkey") |
| parser_add_list(ibpkey_action, "ibpkey") |
| parser_add_extract(ibpkey_action, "ibpkey") |
| parser_add_deleteall(ibpkey_action, "ibpkey") |
| parser_add_type(ibpkeyParser, "ibpkey") |
| parser_add_range(ibpkeyParser, "ibpkey") |
| parser_add_subnet_prefix(ibpkeyParser, "ibpkey") |
| ibpkeyParser.add_argument('ibpkey', nargs='?', default=None, help=_('pkey | pkey_range')) |
| ibpkeyParser.set_defaults(func=handlePkey) |
| |
| def handleIbendport(args): |
| ibendport_args = {'list': [('ibendport', 'type', 'ibdev_name'), ('')], 'add': [('locallist'), ('type', 'ibendport', 'ibdev_name'), ('')], 'modify': [('localist'), ('ibendport', 'ibdev_name')], 'delete': [('locallist'), ('ibendport', 'ibdev_name')], 'extract': [('locallist', 'ibendport', 'type', 'ibdev_name'), ('')], 'deleteall': [('locallist'), ('')]} |
| |
| handle_opts(args, ibendport_args, args.action) |
| |
| OBJECT = object_dict['ibendport'](args) |
| |
| if args.action == "add": |
| OBJECT.add(args.ibendport, args.ibdev_name, args.range, args.type) |
| if args.action == "modify": |
| OBJECT.modify(args.ibendport, args.ibdev_name, args.range, args.type) |
| if args.action == "delete": |
| OBJECT.delete(args.ibendport, args.ibdev_name) |
| if args.action == "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action == "deleteall": |
| OBJECT.deleteall() |
| if args.action == "extract": |
| for i in OBJECT.customized(): |
| print("ibendport %s" % str(i)) |
| |
| |
| def setupIbendportParser(subparsers): |
| generated_usage = generate_custom_usage(usage_ibendport, usage_ibendport_dict) |
| ibendportParser = subparsers.add_parser('ibendport', usage=generated_usage, help=_('Manage infiniband end port type definitions')) |
| parser_add_locallist(ibendportParser, "ibendport") |
| parser_add_noheading(ibendportParser, "ibendport") |
| parser_add_noreload(ibendportParser, "ibendport") |
| parser_add_store(ibendportParser, "ibendport") |
| |
| ibendport_action = ibendportParser.add_mutually_exclusive_group(required=True) |
| parser_add_add(ibendport_action, "ibendport") |
| parser_add_delete(ibendport_action, "ibendport") |
| parser_add_modify(ibendport_action, "ibendport") |
| parser_add_list(ibendport_action, "ibendport") |
| parser_add_extract(ibendport_action, "ibendport") |
| parser_add_deleteall(ibendport_action, "ibendport") |
| parser_add_type(ibendportParser, "ibendport") |
| parser_add_range(ibendportParser, "ibendport") |
| parser_add_ibdev_name(ibendportParser, "ibendport") |
| ibendportParser.add_argument('ibendport', nargs='?', default=None, help=_('ibendport')) |
| ibendportParser.set_defaults(func=handleIbendport) |
| |
| def handleInterface(args): |
| interface_args = {'list': [('interface'), ('')], 'add': [('locallist'), ('type', 'interface')], 'modify': [('locallist'), ('type', 'interface')], 'delete': [('locallist'), ('interface')], 'extract': [('locallist', 'interface', 'type'), ('')], 'deleteall': [('locallist'), ('')]} |
| |
| handle_opts(args, interface_args, args.action) |
| |
| OBJECT = object_dict['interface'](args) |
| |
| if args.action == "add": |
| OBJECT.add(args.interface, args.range, args.type) |
| if args.action == "modify": |
| OBJECT.modify(args.interface, args.range, args.type) |
| if args.action == "delete": |
| OBJECT.delete(args.interface) |
| if args.action == "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action == "deleteall": |
| OBJECT.deleteall() |
| if args.action == "extract": |
| for i in OBJECT.customized(): |
| print("interface %s" % str(i)) |
| |
| |
| def setupInterfaceParser(subparsers): |
| generated_usage = generate_custom_usage(usage_interface, usage_interface_dict) |
| interfaceParser = subparsers.add_parser('interface', usage=generated_usage, help=_('Manage network interface type definitions')) |
| parser_add_locallist(interfaceParser, "interface") |
| parser_add_noheading(interfaceParser, "interface") |
| parser_add_noreload(interfaceParser, "interface") |
| parser_add_store(interfaceParser, "interface") |
| parser_add_type(interfaceParser, "interface") |
| parser_add_range(interfaceParser, "interface") |
| |
| interface_action = interfaceParser.add_mutually_exclusive_group(required=True) |
| parser_add_add(interface_action, "interface") |
| parser_add_delete(interface_action, "interface") |
| parser_add_modify(interface_action, "interface") |
| parser_add_list(interface_action, "interface") |
| parser_add_extract(interface_action, "interface") |
| parser_add_deleteall(interface_action, "interface") |
| interfaceParser.add_argument('interface', nargs='?', default=None, help=_('interface_spec')) |
| interfaceParser.set_defaults(func=handleInterface) |
| |
| |
| def handleModule(args): |
| OBJECT = seobject.moduleRecords(args) |
| if args.action_add: |
| OBJECT.add(args.action_add[0], args.priority) |
| if args.action_enable: |
| OBJECT.set_enabled(" ".join(args.action_enable), True) |
| if args.action_disable: |
| OBJECT.set_enabled(" ".join(args.action_disable), False) |
| if args.action_remove: |
| OBJECT.delete(" ".join(args.action_remove), args.priority) |
| if args.action == "deleteall": |
| OBJECT.deleteall() |
| if args.action == "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action == "extract": |
| for i in OBJECT.customized(): |
| print("module %s" % str(i)) |
| |
| |
| def setupModuleParser(subparsers): |
| moduleParser = subparsers.add_parser('module', help=_('Manage SELinux policy modules')) |
| parser_add_noheading(moduleParser, "module") |
| parser_add_noreload(moduleParser, "module") |
| parser_add_store(moduleParser, "module") |
| parser_add_locallist(moduleParser, "module") |
| parser_add_priority(moduleParser, "module") |
| |
| mgroup = moduleParser.add_mutually_exclusive_group(required=True) |
| parser_add_list(mgroup, "module") |
| parser_add_extract(mgroup, "module") |
| parser_add_deleteall(mgroup, "module") |
| mgroup.add_argument('-a', '--add', dest='action_add', action='store', nargs=1, metavar='module_name', help=_("Add a module")) |
| mgroup.add_argument('-r', '--remove', dest='action_remove', action='store', nargs='+', metavar='module_name', help=_("Remove a module")) |
| mgroup.add_argument('-d', '--disable', dest='action_disable', action='store', nargs='+', metavar='module_name', help=_("Disable a module")) |
| mgroup.add_argument('-e', '--enable', dest='action_enable', action='store', nargs='+', metavar='module_name', help=_("Enable a module")) |
| moduleParser.set_defaults(func=handleModule) |
| |
| |
| def handleNode(args): |
| node_args = {'list': [('node', 'type', 'proto', 'netmask'), ('')], 'add': [('locallist'), ('type', 'node', 'proto', 'netmask')], 'modify': [('locallist'), ('node', 'netmask', 'proto')], 'delete': [('locallist'), ('node', 'netmask', 'prototype')], 'extract': [('locallist', 'node', 'type', 'proto', 'netmask'), ('')], 'deleteall': [('locallist'), ('')]} |
| handle_opts(args, node_args, args.action) |
| |
| OBJECT = object_dict['node'](args) |
| |
| if args.action == "add": |
| OBJECT.add(args.node, args.netmask, args.proto, args.range, args.type) |
| if args.action == "modify": |
| OBJECT.modify(args.node, args.netmask, args.proto, args.range, args.type) |
| if args.action == "delete": |
| OBJECT.delete(args.node, args.netmask, args.proto) |
| if args.action == "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action == "deleteall": |
| OBJECT.deleteall() |
| if args.action == "extract": |
| for i in OBJECT.customized(): |
| print("node %s" % str(i)) |
| |
| |
| def setupNodeParser(subparsers): |
| generated_usage = generate_custom_usage(usage_node, usage_node_dict) |
| nodeParser = subparsers.add_parser('node', usage=generated_usage, help=_('Manage network node type definitions')) |
| parser_add_locallist(nodeParser, "node") |
| parser_add_noheading(nodeParser, "node") |
| parser_add_noreload(nodeParser, "node") |
| parser_add_store(nodeParser, "node") |
| |
| node_action = nodeParser.add_mutually_exclusive_group(required=True) |
| parser_add_add(node_action, "node") |
| parser_add_delete(node_action, "node") |
| parser_add_modify(node_action, "node") |
| parser_add_list(node_action, "node") |
| parser_add_extract(node_action, "node") |
| parser_add_deleteall(node_action, "node") |
| |
| nodeParser.add_argument('-M', '--netmask', help=_('Network Mask')) |
| parser_add_type(nodeParser, "node") |
| parser_add_range(nodeParser, "node") |
| parser_add_proto(nodeParser, "node") |
| nodeParser.add_argument('node', nargs='?', default=None, help=_('node')) |
| nodeParser.set_defaults(func=handleNode) |
| |
| |
| def handleBoolean(args): |
| boolean_args = {'list': [('state', 'boolean'), ('')], 'modify': [('localist'), ('boolean', 'state')], 'extract': [('locallist', 'state', 'boolean'), ('')], 'deleteall': [('locallist'), ('')], 'state': [('locallist', 'list', 'extract', 'deleteall'), ('modify')]} |
| |
| handle_opts(args, boolean_args, args.action) |
| |
| OBJECT = object_dict['boolean'](args) |
| |
| if args.action == "modify": |
| if args.boolean: |
| OBJECT.modify(args.boolean, args.state, False) |
| if args.action == "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action == "deleteall": |
| OBJECT.deleteall() |
| if args.action == "extract": |
| for i in OBJECT.customized(): |
| print("boolean %s" % str(i)) |
| |
| |
| def setupBooleanParser(subparsers): |
| generated_usage = generate_custom_usage(usage_boolean, usage_boolean_dict) |
| booleanParser = subparsers.add_parser('boolean', usage=generated_usage, help=_('Manage booleans to selectively enable functionality')) |
| parser_add_locallist(booleanParser, "boolean") |
| parser_add_noheading(booleanParser, "boolean") |
| parser_add_noreload(booleanParser, "boolean") |
| parser_add_store(booleanParser, "boolean") |
| booleanParser.add_argument('boolean', nargs="?", default=None, help=_('boolean')) |
| |
| boolean_action = booleanParser.add_mutually_exclusive_group(required=True) |
| #add_add(boolean_action) |
| parser_add_modify(boolean_action, "boolean") |
| parser_add_list(boolean_action, "boolean") |
| parser_add_extract(boolean_action, "boolean") |
| parser_add_deleteall(boolean_action, "boolean") |
| |
| booleanGroup = booleanParser.add_mutually_exclusive_group(required=False) |
| booleanGroup.add_argument('-1', '--on', dest='state', action='store_const', const='on', help=_('Enable the boolean')) |
| booleanGroup.add_argument('-0', '--off', dest='state', action='store_const', const='off', help=_('Disable the boolean')) |
| |
| booleanParser.set_defaults(func=handleBoolean) |
| |
| |
| def handlePermissive(args): |
| OBJECT = object_dict['permissive'](args) |
| |
| if args.action == "list": |
| OBJECT.list(args.noheading) |
| elif args.action == "deleteall": |
| OBJECT.deleteall() |
| elif args.action == "extract": |
| for i in OBJECT.customized(): |
| print("permissive %s" % str(i)) |
| elif args.type is not None: |
| if args.action == "add": |
| OBJECT.add(args.type) |
| if args.action == "delete": |
| OBJECT.delete(args.type) |
| else: |
| args.parser.error(message=_('semanage permissive: error: the following argument is required: type\n')) |
| |
| |
| def setupPermissiveParser(subparsers): |
| permissiveParser = subparsers.add_parser('permissive', help=_('Manage process type enforcement mode')) |
| |
| pgroup = permissiveParser.add_mutually_exclusive_group(required=True) |
| parser_add_add(pgroup, "permissive") |
| parser_add_delete(pgroup, "permissive") |
| parser_add_deleteall(pgroup, "permissive") |
| parser_add_extract(pgroup, "permissive") |
| parser_add_list(pgroup, "permissive") |
| |
| parser_add_noheading(permissiveParser, "permissive") |
| parser_add_noreload(permissiveParser, "permissive") |
| parser_add_store(permissiveParser, "permissive") |
| permissiveParser.add_argument('type', nargs='?', default=None, help=_('type')) |
| permissiveParser.set_defaults(func=handlePermissive) |
| permissiveParser.set_defaults(parser=permissiveParser) |
| |
| |
| def handleDontaudit(args): |
| OBJECT = object_dict['dontaudit'](args) |
| OBJECT.toggle(args.action) |
| |
| |
| def setupDontauditParser(subparsers): |
| dontauditParser = subparsers.add_parser('dontaudit', help=_('Disable/Enable dontaudit rules in policy')) |
| parser_add_noreload(dontauditParser, "dontaudit") |
| parser_add_store(dontauditParser, "dontaudit") |
| dontauditParser.add_argument('action', choices=["on", "off"]) |
| dontauditParser.set_defaults(func=handleDontaudit) |
| |
| |
| def handleExport(args): |
| manageditems = ["boolean", "login", "interface", "user", "port", "node", "fcontext", "module", "ibendport", "ibpkey", "permissive"] |
| for i in manageditems: |
| print("%s -D" % i) |
| for i in manageditems: |
| OBJECT = object_dict[i](args) |
| for c in OBJECT.customized(): |
| print("%s %s" % (i, str(c))) |
| |
| sys.exit(0) |
| |
| |
| def setupExportParser(subparsers): |
| exportParser = subparsers.add_parser('export', help=_('Output local customizations')) |
| parser_add_store(exportParser, "export") |
| exportParser.add_argument('-f', '--output_file', dest='output_file', action=SetExportFile, help=_('Output file')) |
| exportParser.set_defaults(func=handleExport) |
| |
| import re |
| |
| |
| def mkargv(line): |
| dquote = "\"" |
| squote = "\'" |
| l = line.split() |
| ret = [] |
| i = 0 |
| while i < len(l): |
| cnt = len(re.findall(dquote, l[i])) |
| if cnt > 1: |
| ret.append(l[i].strip(dquote)) |
| i = i + 1 |
| continue |
| if cnt == 1: |
| quote = [l[i].strip(dquote)] |
| i = i + 1 |
| |
| while i < len(l) and dquote not in l[i]: |
| quote.append(l[i]) |
| i = i + 1 |
| quote.append(l[i].strip(dquote)) |
| ret.append(" ".join(quote)) |
| i = i + 1 |
| continue |
| |
| cnt = len(re.findall(squote, l[i])) |
| if cnt > 1: |
| ret.append(l[i].strip(squote)) |
| i = i + 1 |
| continue |
| if cnt == 1: |
| quote = [l[i].strip(squote)] |
| i = i + 1 |
| while i < len(l) and squote not in l[i]: |
| quote.append(l[i]) |
| i = i + 1 |
| |
| quote.append(l[i].strip(squote)) |
| ret.append(" ".join(quote)) |
| i = i + 1 |
| continue |
| |
| ret.append(l[i]) |
| i = i + 1 |
| |
| return ret |
| |
| |
| def handleImport(args): |
| trans = seobject.semanageRecords(args) |
| trans.start() |
| |
| for l in sys.stdin.readlines(): |
| if len(l.strip()) == 0: |
| continue |
| |
| try: |
| commandParser = createCommandParser() |
| args = commandParser.parse_args(mkargv(l)) |
| args.func(args) |
| except ValueError as e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e))) |
| sys.exit(1) |
| except IOError as e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e))) |
| sys.exit(1) |
| except KeyboardInterrupt: |
| sys.exit(0) |
| |
| trans.finish() |
| |
| |
| def setupImportParser(subparsers): |
| importParser = subparsers.add_parser('import', help=_('Import local customizations')) |
| parser_add_noreload(importParser, "import") |
| parser_add_store(importParser, "import") |
| importParser.add_argument('-f', '--input_file', dest='input_file', action=SetImportFile, help=_('Input file')) |
| importParser.set_defaults(func=handleImport) |
| |
| |
| def createCommandParser(): |
| commandParser = seParser(prog='semanage', |
| formatter_class=argparse.ArgumentDefaultsHelpFormatter, |
| description='''semanage is used to configure certain elements |
| of SELinux policy with-out requiring modification |
| to or recompilation from policy source.''') |
| |
| #To add a new subcommand define the parser for it in a function above and call it here. |
| subparsers = commandParser.add_subparsers(dest='subcommand') |
| subparsers.required = True |
| setupImportParser(subparsers) |
| setupExportParser(subparsers) |
| setupLoginParser(subparsers) |
| setupUserParser(subparsers) |
| setupPortParser(subparsers) |
| setupPkeyParser(subparsers) |
| setupIbendportParser(subparsers) |
| setupInterfaceParser(subparsers) |
| setupModuleParser(subparsers) |
| setupNodeParser(subparsers) |
| setupFcontextParser(subparsers) |
| setupBooleanParser(subparsers) |
| setupPermissiveParser(subparsers) |
| setupDontauditParser(subparsers) |
| |
| return commandParser |
| |
| |
| def make_io_args(args): |
| # import/export backward compatibility |
| args_origin = ["-S", "-o", "-i", "targeted", "minimum", "mls"] |
| args_file = [] |
| args_ie = [] |
| args_subcommand = [] |
| |
| for i in args: |
| if i == "-o": |
| args_subcommand = ["export"] |
| continue |
| if i == "-i": |
| args_subcommand = ["import"] |
| continue |
| if i not in args_origin: |
| args_file = ["-f", i] |
| continue |
| args_ie.append(i) |
| |
| return args_subcommand + args_ie + args_file |
| |
| |
| def make_args(sys_args): |
| args = [] |
| if "-o" in sys_args[1:] or "-i" in sys_args[1:]: |
| args = make_io_args(sys_args[1:]) |
| else: |
| args = sys_args[1:] |
| |
| return args |
| |
| |
| def do_parser(): |
| try: |
| commandParser = createCommandParser() |
| args = commandParser.parse_args(make_args(sys.argv)) |
| args.func(args) |
| sys.exit(0) |
| except IOError as e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e))) |
| sys.exit(1) |
| except KeyboardInterrupt: |
| sys.exit(0) |
| except ValueError as e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, e.args[0])) |
| sys.exit(1) |
| except KeyError as e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, e.args[0])) |
| sys.exit(1) |
| except OSError as e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, e.args[1])) |
| sys.exit(1) |
| except RuntimeError as e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, e.args[0])) |
| sys.exit(1) |
| |
| if __name__ == '__main__': |
| do_parser() |