| #! /usr/bin/python -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 argparse |
| import seobject |
| import sys |
| import gettext |
| PROGNAME="policycoreutils" |
| try: |
| gettext.install(PROGNAME, |
| localedir="/usr/share/locale", |
| unicode=True, |
| codeset = 'utf-8') |
| except IOError: |
| 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','-s SEUSER','selinux_name'')'),' --delete':('selinux_name',),' --modify':('(','-L LEVEL','-R ROLES','-r RANGE','-s SEUSER','selinux_name',')'),' --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_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':('',)} |
| |
| import sepolicy |
| class CheckRole(argparse.Action): |
| def __call__(self, parser, namespace, value, option_string=None): |
| newval = getattr(namespace, self.dest) |
| if not newval: |
| newval = [] |
| roles = sepolicy.get_all_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) |
| |
| store = '' |
| class SetStore(argparse.Action): |
| def __call__(self, parser, namespace, values, option_string=None): |
| global store |
| store=values |
| setattr(namespace, self.dest, values) |
| |
| class seParser(argparse.ArgumentParser): |
| def error(self, message): |
| if len(sys.argv) == 2: |
| self.print_help() |
| sys.exit(2) |
| 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 is not "-": |
| try: |
| sys.stdout = open(values, 'w') |
| except: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e))) |
| 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 is not "-": |
| try: |
| sys.stdin = open(values, 'r') |
| except IOError,e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e))) |
| sys.exit(1) |
| setattr(namespace, self.dest, values) |
| |
| # functions for OBJECT initialization |
| def login_ini(): |
| OBJECT = seobject.loginRecords(store) |
| return OBJECT |
| |
| def user_ini(): |
| OBJECT = seobject.seluserRecords(store) |
| return OBJECT |
| |
| def port_ini(): |
| OBJECT = seobject.portRecords(store) |
| return OBJECT |
| |
| def module_ini(): |
| OBJECT = seobject.moduleRecords(store) |
| return OBJECT |
| |
| def interface_ini(): |
| OBJECT = seobject.interfaceRecords(store) |
| return OBJECT |
| |
| def node_ini(): |
| OBJECT = seobject.nodeRecords(store) |
| return OBJECT |
| |
| def fcontext_ini(): |
| OBJECT = seobject.fcontextRecords(store) |
| return OBJECT |
| |
| def boolean_ini(): |
| OBJECT = seobject.booleanRecords(store) |
| return OBJECT |
| |
| def permissive_ini(): |
| OBJECT = seobject.permissiveRecords(store) |
| return OBJECT |
| |
| def dontaudit_ini(): |
| OBJECT = seobject.dontauditClass(store) |
| return OBJECT |
| |
| # define dictonary for seobject OBEJCTS |
| object_dict = {'login':login_ini, 'user':user_ini, 'port':port_ini, 'module':module_ini, 'interface':interface_ini, 'node':node_ini, 'fcontext':fcontext_ini, 'boolean':boolean_ini,'permissive':permissive_ini, 'dontaudit':dontaudit_ini} |
| |
| 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']() |
| OBJECT.set_reload(args.noreload) |
| |
| if args.action is "add": |
| OBJECT.add(args.login, args.seuser, args.range) |
| if args.action is "modify": |
| OBJECT.modify(args.login, args.seuser, args.range) |
| if args.action is "delete": |
| OBJECT.delete(args.login) |
| if args.action is "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action is "deleteall": |
| OBJECT.deleteall() |
| if args.action is "extract": |
| for i in OBJECT.customized(): |
| print "login %s" % (str(i)) |
| |
| def parser_add_store(parser, name): |
| parser.add_argument('-S', '--store', action=SetStore, 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_false', default=True, 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_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 is None: |
| print("usage: "+"%s" % generate_custom_usage(usage_fcontext, usage_fcontext_dict)) |
| sys.exit(2) |
| elif args.action and args.equal: |
| handle_opts(args, fcontext_equal_args, "equal") |
| else: |
| handle_opts(args, fcontext_args, args.action) |
| |
| OBJECT = object_dict['fcontext']() |
| OBJECT.set_reload(args.noreload) |
| |
| if args.action is "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 is "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 is "delete": |
| if args.equal: |
| OBJECT.delete(args.file_spec, args.equal) |
| else: |
| OBJECT.delete(args.file_spec,args.ftype) |
| if args.action is "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action is "deleteall": |
| OBJECT.deleteall() |
| if args.action is "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 -- to match only regular files. The following |
| file type options can be passed: |
| -- (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=False) |
| 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']() |
| OBJECT.set_reload(args.noreload) |
| |
| if args.action is "add": |
| OBJECT.add(args.selinux_name, args.roles, args.level, args.range, args.prefix) |
| if args.action is "modify": |
| OBJECT.modify(args.selinux_name, args.roles, args.level, args.range, args.prefix) |
| if args.action is "delete": |
| OBJECT.delete(args.selinux_name) |
| if args.action is "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action is "deleteall": |
| OBJECT.deleteall() |
| if args.action is "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']() |
| OBJECT.set_reload(args.noreload) |
| |
| if args.action is "add": |
| OBJECT.add(args.port, args.proto, args.range, args.type) |
| if args.action is "modify": |
| OBJECT.modify(args.port, args.proto, args.range, args.type) |
| if args.action is "delete": |
| OBJECT.delete(args.port, args.proto) |
| if args.action is "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action is "deleteall": |
| OBJECT.deleteall() |
| if args.action is "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 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']() |
| OBJECT.set_reload(args.noreload) |
| |
| if args.action is "add": |
| OBJECT.add(args.interface, args.range, args.type) |
| if args.action is "modify": |
| OBJECT.add(args.interface, args.range, args.type) |
| if args.action is "delete": |
| OBJECT.delete(args.interface) |
| if args.action is "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action is "deleteall": |
| OBJECT.deleteall() |
| if args.action is "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(store) |
| OBJECT.set_reload(args.noreload) |
| if args.action == "add": |
| OBJECT.add(args.module_name, args.priority) |
| if args.action == "enable": |
| OBJECT.set_enabled(args.module_name, True) |
| if args.action == "disable": |
| OBJECT.set_enabled(args.module_name, False) |
| if args.action == "remove": |
| OBJECT.delete(args.module_name, args.priority) |
| if args.action is "deleteall": |
| OBJECT.deleteall() |
| if args.action == "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action is "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_add(mgroup, "module") |
| parser_add_list(mgroup, "module") |
| parser_add_extract(mgroup, "module") |
| parser_add_deleteall(mgroup, "module") |
| mgroup.add_argument('-r', '--remove', dest='action', action='store_const', const='remove', help=_("Remove a module")) |
| mgroup.add_argument('-d', '--disable', dest='action', action='store_const', const='disable', help=_("Disable a module")) |
| mgroup.add_argument('-e', '--enable', dest='action', action='store_const', const='enable', help=_("Enable a module")) |
| moduleParser.add_argument('module_name', nargs='?', default=None, help=_('Name of the module to act on')) |
| 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']() |
| OBJECT.set_reload(args.noreload) |
| |
| if args.action is "add": |
| OBJECT.add(args.node, args.netmask, args.proto, args.range, args.type) |
| if args.action is "modify": |
| OBJECT.add(args.node, args.netmask, args.proto, args.range, args.type) |
| if args.action is "delete": |
| OBJECT.delete(args.node, args.netmask, args.proto) |
| if args.action is "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action is "deleteall": |
| OBJECT.deleteall() |
| if args.action is "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'),('')], 'extract':[('locallist','state','boolean'),('')],'deleteall':[('locallist'),('')],'state':[('locallist','list','extract','deleteall'),('modify')]} |
| if args.action is None: |
| print("Usage: "+"%s" % generate_custom_usage(usage_boolean, usage_boolean_dict)) |
| sys.exit(2) |
| # TODO: should be added to handle_opts logic |
| elif args.action is "modify" and not args.boolean: |
| print "boolean name required " |
| sys.exit(1) |
| elif args.action is "modify" and args.boolean and not args.state: |
| print "state option is needed" |
| sys.exit(1) |
| else: |
| handle_opts(args,boolean_args,args.action) |
| |
| OBJECT = object_dict['boolean']() |
| OBJECT.set_reload(args.noreload) |
| |
| if args.action is "modify": |
| if args.boolean: |
| OBJECT.modify(args.boolean, args.state, False) |
| if args.action is "list": |
| OBJECT.list(args.noheading, args.locallist) |
| if args.action is "deleteall": |
| OBJECT.deleteall() |
| if args.action is "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=False) |
| #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']() |
| OBJECT.set_reload(args.noreload) |
| |
| if args.action is "add": |
| OBJECT.add(args.type) |
| if args.action is "list": |
| OBJECT.list(args.noheading) |
| if args.action is "delete": |
| OBJECT.delete(args.type) |
| |
| 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) |
| |
| def handleDontaudit(args): |
| OBJECT = object_dict['dontaudit']() |
| OBJECT.set_reload(args.noreload) |
| 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"] |
| for i in manageditems: |
| print "%s -D" % i |
| for i in manageditems: |
| OBJECT = object_dict[i]() |
| 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(store) |
| 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,e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e))) |
| sys.exit(1) |
| except IOError,e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e))) |
| sys.exit(1) |
| except KeyboardInterrupt: |
| sys.exit(0) |
| |
| trans.set_reload(args.noreload) |
| trans.finish() |
| |
| def setupImportParser(subparsers): |
| importParser = subparsers.add_parser('import', help=_('Output 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') |
| setupImportParser(subparsers) |
| setupExportParser(subparsers) |
| setupLoginParser(subparsers) |
| setupUserParser(subparsers) |
| setupPortParser(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", "minumum", "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,e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e))) |
| sys.exit(1) |
| except KeyboardInterrupt: |
| sys.exit(0) |
| except ValueError, e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, e.args[0])) |
| sys.exit(1) |
| except KeyError, e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, e.args[0])) |
| sys.exit(1) |
| except OSError, e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, e.args[1])) |
| sys.exit(1) |
| except RuntimeError, e: |
| sys.stderr.write("%s: %s\n" % (e.__class__.__name__, e.args[0])) |
| sys.exit(1) |
| |
| if __name__ == '__main__': |
| do_parser() |