blob: 0c7c1862871a252ce3a1df21222ac090546c5bc8 [file] [log] [blame]
#! /usr/bin/python -Es
# Copyright (C) 2005, 2006, 2007 Red Hat
# 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 sys, getopt, re
import seobject
import selinux
PROGNAME="policycoreutils"
import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
gettext.textdomain(PROGNAME)
try:
gettext.install(PROGNAME,
localedir="/usr/share/locale",
unicode=False,
codeset = 'utf-8')
except IOError:
import __builtin__
__builtin__.__dict__['_'] = unicode
if __name__ == '__main__':
manageditems=[ "boolean", "login", "user", "port", "interface", "node", "fcontext"]
action = False
def set_action(option):
global action
if action:
raise ValueError(_("%s bad option") % option)
action = True
def usage(message = ""):
text = _("""
semanage [ -S store ] -i [ input_file | - ]
semanage [ -S store ] -o [ output_file | - ]
semanage login -{a|d|m|l|D|E} [-nsr] login_name | %groupname
semanage user -{a|d|m|l|D|E} [-LnrRP] selinux_name
semanage port -{a|d|m|l|D|E} [-ntr] [ -p proto ] port | port_range
semanage interface -{a|d|m|l|D|E} [-ntr] interface_spec
semanage module -{a|d|m} [--enable|--disable] module
semanage node -{a|d|m|l|D|E} [-ntr] [ -p protocol ] [-M netmask] addr
semanage fcontext -{a|d|m|l|D|E} [-efnrst] file_spec
semanage boolean -{d|m} [--on|--off|-1|-0] -F boolean | boolean_file
semanage permissive -{d|a|l} [-n] type
semanage dontaudit [ on | off ]
Primary Options:
-a, --add Add a OBJECT record NAME
-d, --delete Delete a OBJECT record NAME
-m, --modify Modify a OBJECT record NAME
-i, --input Input multiple semange commands in a transaction
-o, --output Output current customizations as semange commands
-l, --list List the OBJECTS
-E, --extract extract customizable commands
-C, --locallist List OBJECTS local customizations
-D, --deleteall Remove all OBJECTS local customizations
-h, --help Display this message
-n, --noheading Do not print heading when listing OBJECTS
-S, --store Select and alternate SELinux store to manage
Object-specific Options (see above):
-f, --ftype File Type of OBJECT
"" (all files)
-- (regular file)
-d (directory)
-c (character device)
-b (block device)
-s (socket)
-l (symbolic link)
-p (named pipe)
-F, --file Treat target as an input file for command, change multiple settings
-p, --proto Port protocol (tcp or udp) or internet protocol version of node (ipv4 or ipv6)
-M, --mask Netmask
-e, --equal Substitue source path for dest path when labeling
-P, --prefix Prefix for home directory labeling
-L, --level Default SELinux Level (MLS/MCS Systems only)
-R, --roles SELinux Roles (ex: "sysadm_r staff_r")
-s, --seuser SELinux User Name
-t, --type SELinux Type for the object
-r, --range MLS/MCS Security Range (MLS/MCS Systems only)
--enable Enable a module
--disable Disable a module
""")
raise ValueError("%s\n%s" % (text, message))
def errorExit(error):
sys.stderr.write("%s: " % sys.argv[0])
sys.stderr.write("%s\n" % error)
sys.stderr.flush()
sys.exit(1)
def get_options():
valid_option={}
valid_everyone=[ '-a', '--add', '-d', '--delete', '-m', '--modify', '-l', '--list', '-h', '--help', '-n', '--noheading', '-S', '--store' ]
valid_local=[ '-E', '--extract', '-C', '--locallist', '-D', '--deleteall']
valid_option["login"] = []
valid_option["login"] += valid_everyone + valid_local + [ '-s', '--seuser', '-r', '--range']
valid_option["user"] = []
valid_option["user"] += valid_everyone + valid_local + [ '-L', '--level', '-r', '--range', '-R', '--roles', '-P', '--prefix' ]
valid_option["port"] = []
valid_option["port"] += valid_everyone + valid_local + [ '-t', '--type', '-r', '--range', '-p', '--proto' ]
valid_option["interface"] = []
valid_option["interface"] += valid_everyone + valid_local + [ '-t', '--type', '-r', '--range']
valid_option["node"] = []
valid_option["node"] += valid_everyone + valid_local + [ '-M', '--mask', '-t', '--type', '-r', '--range', '-p', '--protocol']
valid_option["module"] = []
valid_option["module"] += valid_everyone + [ '--enable', '--disable']
valid_option["fcontext"] = []
valid_option["fcontext"] += valid_everyone + valid_local + [ '-e', '--equal', '-f', '--ftype', '-s', '--seuser', '-t', '--type', '-r', '--range']
valid_option["dontaudit"] = [ '-S', '--store' ]
valid_option["boolean"] = []
valid_option["boolean"] += valid_everyone + valid_local + [ '--on', "--off", "-1", "-0", "-F", "--file"]
valid_option["permissive"] = []
valid_option["permissive"] += [ '-a', '--add', '-d', '--delete', '-l', '--list', '-h', '--help', '-n', '--noheading', '-D', '--deleteall' ]
return valid_option
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 process_args(argv):
global action
action = False
serange = ""
port = ""
proto = ""
mask = ""
selevel = ""
setype = ""
ftype = ""
roles = ""
seuser = ""
prefix = "user"
heading = True
value = None
add = False
modify = False
delete = False
deleteall = False
enable = False
extract = False
disable = False
list = False
locallist = False
use_file = False
store = ""
equal = ""
if len(argv) == 0:
return
object = argv[0]
option_dict=get_options()
if object not in option_dict.keys():
usage(_("Invalid parameter %s not defined") % object)
args = argv[1:]
try:
gopts, cmds = getopt.getopt(args,
'01adEe:f:i:lhmnp:s:FCDR:L:r:t:P:S:M:',
['add',
'delete',
'deleteall',
'enable',
'equal=',
'extract',
'disable',
'ftype=',
'file',
'help',
'input=',
'list',
'modify',
'noheading',
'localist',
'off',
'on',
'proto=',
'seuser=',
'store=',
'range=',
'locallist=',
'level=',
'roles=',
'type=',
'prefix=',
'mask='
])
except getopt.error, error:
usage(_("Options Error %s ") % error.msg)
for o, a in gopts:
if o not in option_dict[object]:
sys.stderr.write(_("%s not valid for %s objects\n") % ( o, object) );
return
for o,a in gopts:
if o == "-a" or o == "--add":
set_action(o)
add = True
if o == "-d" or o == "--delete":
set_action(o)
delete = True
if o == "-D" or o == "--deleteall":
set_action(o)
deleteall = True
if o == "-E" or o == "--extract":
set_action(o)
extract = True
if o == "-f" or o == "--ftype":
ftype=a
if o == "-e" or o == "--equal":
equal = a
if o == "--enable":
set_action(o)
enable = True
if o == "--disable":
set_action(o)
disable = True
if o == "-F" or o == "--file":
use_file = True
if o == "-h" or o == "--help":
raise usage()
if o == "-n" or o == "--noheading":
heading = False
if o == "-C" or o == "--locallist":
locallist = True
if o == "-m"or o == "--modify":
set_action(o)
modify = True
if o == "-S" or o == '--store':
store = a
if o == "-r" or o == '--range':
serange = a
if o == "-l" or o == "--list":
list = True
if o == "-L" or o == '--level':
selevel = a
if o == "-p" or o == '--proto':
proto = a
if o == "-P" or o == '--prefix':
prefix = a
if o == "-R" or o == '--roles':
roles = roles + " " + a
if o == "-s" or o == "--seuser":
seuser = a
if o == "-M" or o == '--mask':
mask = a
if o == "-t" or o == "--type":
setype = a
if o == "--on" or o == "-1":
value = "on"
modify = True
if o == "--off" or o == "-0":
value = "off"
modify = True
if object == "login":
OBJECT = seobject.loginRecords(store)
if object == "user":
OBJECT = seobject.seluserRecords(store)
if object == "port":
OBJECT = seobject.portRecords(store)
if object == "interface":
OBJECT = seobject.interfaceRecords(store)
if object == "node":
OBJECT = seobject.nodeRecords(store)
if object == "fcontext":
OBJECT = seobject.fcontextRecords(store)
if object == "boolean":
OBJECT = seobject.booleanRecords(store)
if use_file:
modify = True
if object == "module":
OBJECT = seobject.moduleRecords(store)
if object == "permissive":
OBJECT = seobject.permissiveRecords(store)
if list:
if object == "boolean":
OBJECT.list(heading, locallist, use_file)
else:
OBJECT.list(heading, locallist)
return
if deleteall:
OBJECT.deleteall()
return
if extract:
for i in OBJECT.customized():
print "%s %s" % (object, str(i))
return
if len(cmds) != 1:
raise ValueError(_("bad option"))
target = cmds[0]
if object == "dontaudit":
OBJECT = seobject.dontauditClass(store)
OBJECT.toggle(target)
return
if add:
if object == "login":
OBJECT.add(target, seuser, serange)
return
if object == "user":
OBJECT.add(target, roles.split(), selevel, serange, prefix)
return
if object == "port":
OBJECT.add(target, proto, serange, setype)
return
if object == "interface":
OBJECT.add(target, serange, setype)
return
if object == "module":
OBJECT.add(target)
return
if object == "node":
OBJECT.add(target, mask, proto, serange, setype)
return
if object == "fcontext":
if equal == "":
OBJECT.add(target, setype, ftype, serange, seuser)
else:
OBJECT.add_equal(target, equal)
return
if object == "permissive":
OBJECT.add(target)
return
if modify:
if object == "boolean":
OBJECT.modify(target, value, use_file)
return
if object == "login":
OBJECT.modify(target, seuser, serange)
return
if object == "user":
rlist = roles.split()
OBJECT.modify(target, rlist, selevel, serange, prefix)
return
if object == "module":
if enable:
OBJECT.enable(target)
elif disable:
OBJECT.disable(target)
else:
OBJECT.modify(target)
return
if object == "port":
OBJECT.modify(target, proto, serange, setype)
return
if object == "interface":
OBJECT.modify(target, serange, setype)
return
if object == "node":
OBJECT.modify(target, mask, proto, serange, setype)
return
if object == "fcontext":
if equal == "":
OBJECT.modify(target, setype, ftype, serange, seuser)
else:
OBJECT.modify_equal(target, equal)
return
if delete:
if object == "port":
OBJECT.delete(target, proto)
elif object == "fcontext":
OBJECT.delete(target, ftype)
elif object == "node":
OBJECT.delete(target, mask, proto)
else:
OBJECT.delete(target)
return
raise ValueError(_("Invalid command: semanage %s") % " ".join(argv))
#
#
#
try:
output = None
input = None
store = ""
if len(sys.argv) < 3:
usage(_("Requires 2 or more arguments"))
gopts, cmds = getopt.getopt(sys.argv[1:],
'01adf:i:lhmno:p:s:FCDR:L:r:t:P:S:',
['add',
'delete',
'deleteall',
'ftype=',
'file',
'help',
'input=',
'list',
'modify',
'noheading',
'localist',
'off',
'on',
'output=',
'proto=',
'seuser=',
'store=',
'range=',
'level=',
'roles=',
'type=',
'prefix='
])
for o, a in gopts:
if o == "-S" or o == '--store':
store = a
if o == "-i" or o == '--input':
input = a
if o == "-o" or o == '--output':
output = a
if output != None:
if output != "-":
sys.stdout = open(output, 'w')
for i in manageditems:
print "%s -D" % i
process_args([i, "-E"])
sys.exit(0)
if input != None:
if input == "-":
fd = sys.stdin
else:
fd = open(input, 'r')
trans = seobject.semanageRecords(store)
trans.start()
for l in fd.readlines():
process_args(mkargv(l))
trans.finish()
else:
process_args(sys.argv[1:])
except getopt.error, error:
usage(_("Options Error %s ") % error.msg)
except ValueError, error:
errorExit(error.args[0])
except KeyError, error:
errorExit(_("Invalid value %s") % error.args[0])
except IOError, error:
errorExit(error.args[1])
except OSError, error:
errorExit(error.args[1])
except RuntimeError, error:
errorExit(error.args[0])