You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
965 lines
40 KiB
965 lines
40 KiB
#!/usr/bin/python3 -Es |
|
# Copyright (C) 2012-2013 Red Hat |
|
# AUTHOR: Miroslav Grepl <mgrepl@redhat.com> |
|
# AUTHOR: David Quigley <selinux@davequigley.com> |
|
# 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="s0", |
|
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) 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.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_list(pgroup, "permissive") |
|
#TODO: probably should be also added => need to implement own option handling |
|
#parser_add_deleteall(pgroup) |
|
|
|
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"] |
|
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 compability |
|
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()
|
|
|