|
|
68f53e0 |
#! /usr/bin/python -Es
|
|
|
68f53e0 |
# Copyright (C) 2012 Red Hat
|
|
|
68f53e0 |
# AUTHORS: Dan Walsh <dwalsh@redhat.com>
|
|
|
68f53e0 |
# AUTHORS: Miroslav Grepl <mgrepl@redhat.com>
|
|
|
68f53e0 |
# see file 'COPYING' for use and warranty information
|
|
|
68f53e0 |
#
|
|
|
68f53e0 |
# semanage is a tool for managing SELinux configuration files
|
|
|
68f53e0 |
#
|
|
|
68f53e0 |
# This program is free software; you can redistribute it and/or
|
|
|
68f53e0 |
# modify it under the terms of the GNU General Public License as
|
|
|
68f53e0 |
# published by the Free Software Foundation; either version 2 of
|
|
|
68f53e0 |
# the License, or (at your option) any later version.
|
|
|
68f53e0 |
#
|
|
|
68f53e0 |
# This program is distributed in the hope that it will be useful,
|
|
|
68f53e0 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
68f53e0 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
68f53e0 |
# GNU General Public License for more details.
|
|
|
68f53e0 |
#
|
|
|
68f53e0 |
# You should have received a copy of the GNU General Public License
|
|
|
68f53e0 |
# along with this program; if not, write to the Free Software
|
|
|
68f53e0 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
|
68f53e0 |
# 02111-1307 USA
|
|
|
68f53e0 |
#
|
|
|
68f53e0 |
#
|
|
|
68f53e0 |
|
|
|
68f53e0 |
import senetwork
|
|
|
68f53e0 |
import os, sys
|
|
|
68f53e0 |
import selinux
|
|
|
68f53e0 |
import setools, commands
|
|
|
68f53e0 |
import seobject
|
|
|
68f53e0 |
|
|
|
68f53e0 |
import xml.etree.ElementTree
|
|
|
68f53e0 |
modules_dict = {}
|
|
|
68f53e0 |
try:
|
|
|
68f53e0 |
tree = xml.etree.ElementTree.parse("/usr/share/selinux/devel/policy.xml")
|
|
|
68f53e0 |
for l in tree.findall("layer"):
|
|
|
68f53e0 |
for m in l.findall("module"):
|
|
|
68f53e0 |
name = m.get("name")
|
|
|
68f53e0 |
if name == "user" or name == "unconfined":
|
|
|
68f53e0 |
continue
|
|
|
68f53e0 |
if name == "unprivuser":
|
|
|
68f53e0 |
name = "user"
|
|
|
68f53e0 |
if name == "unconfineduser":
|
|
|
68f53e0 |
name = "unconfined"
|
|
|
68f53e0 |
for b in m.findall("summary"):
|
|
|
68f53e0 |
modules_dict[name] = b.text
|
|
|
68f53e0 |
except IOError, e:
|
|
|
68f53e0 |
pass
|
|
|
68f53e0 |
|
|
|
68f53e0 |
all_attributes = map(lambda x: x['name'], setools.seinfo(setools.ATTRIBUTE))
|
|
|
68f53e0 |
|
|
|
68f53e0 |
bools = seobject.booleans_dict.keys()
|
|
|
68f53e0 |
role_allows = {}
|
|
|
68f53e0 |
for rule in commands.getoutput("sesearch --role_allow").split("\n"):
|
|
|
68f53e0 |
role = rule.split()
|
|
|
68f53e0 |
if len(role) == 3 and role[0] == "allow" and role[1] != "system_r" and role[2][:-1] != "system_r":
|
|
|
68f53e0 |
if role[1] not in role_allows:
|
|
|
68f53e0 |
role_allows[role[1]] = [role[2][:-1]]
|
|
|
68f53e0 |
else:
|
|
|
68f53e0 |
role_allows[role[1]].append(role[2][:-1])
|
|
|
68f53e0 |
#role_allows = setools.sesearch([setools.ROLE_ALLOW],{'scontext':self.type,'tcontext':'ping_t', 'class':'process'})
|
|
|
68f53e0 |
roles = []
|
|
|
68f53e0 |
allroles = map(lambda x: x['name'], setools.seinfo(setools.ROLE))
|
|
|
68f53e0 |
for r in allroles:
|
|
|
68f53e0 |
if r not in [ "system_r", "object_r" ]:
|
|
|
68f53e0 |
roles.append(r[:-2])
|
|
|
68f53e0 |
|
|
|
68f53e0 |
types = map(lambda x: x['name'], setools.seinfo(setools.TYPE))
|
|
|
68f53e0 |
|
|
|
68f53e0 |
users = []
|
|
|
68f53e0 |
allusers = map(lambda x: x['name'], setools.seinfo(setools.USER))
|
|
|
68f53e0 |
for u in allusers:
|
|
|
68f53e0 |
if u not in [ "system_u", "root", "unconfined_u" ]:
|
|
|
68f53e0 |
users.append(u.replace("_u",""))
|
|
|
68f53e0 |
users.sort()
|
|
|
68f53e0 |
|
|
|
68f53e0 |
class ManPage:
|
|
|
68f53e0 |
def __init__(self,user,path="/tmp"):
|
|
|
68f53e0 |
self.user = user
|
|
|
68f53e0 |
self.role = user + "_r"
|
|
|
68f53e0 |
self.type = user + "_t"
|
|
|
68f53e0 |
self.fd = open("%s/%s_selinux.8" % (path, self.user), 'w')
|
|
|
68f53e0 |
try:
|
|
|
68f53e0 |
self.desc = modules_dict[self.user]
|
|
|
68f53e0 |
except:
|
|
|
68f53e0 |
self.desc = "%s user role" % self.user
|
|
|
68f53e0 |
|
|
|
68f53e0 |
if self.user in users:
|
|
|
68f53e0 |
self.attributes = setools.seinfo(setools.TYPE,(self.type))[0]["attributes"]
|
|
|
68f53e0 |
self.user_header()
|
|
|
68f53e0 |
self.user_attribute()
|
|
|
68f53e0 |
self.can_sudo()
|
|
|
68f53e0 |
self.xwindows_login()
|
|
|
712fd63 |
self.terminal_login()
|
|
|
68f53e0 |
self.network()
|
|
|
68f53e0 |
self.booleans()
|
|
|
68f53e0 |
self.home_exec()
|
|
|
68f53e0 |
self.transitions()
|
|
|
68f53e0 |
else:
|
|
|
68f53e0 |
self.role_header()
|
|
|
68f53e0 |
|
|
|
68f53e0 |
self.footer()
|
|
|
68f53e0 |
self.fd.close()
|
|
|
68f53e0 |
|
|
|
68f53e0 |
def user_header(self):
|
|
|
68f53e0 |
self.fd.write('.TH "%(type)s_selinux" "8" "%(type)s" "mgrepl@redhat.com" "%(type)s SELinux Policy documentation"'
|
|
|
68f53e0 |
% {'type':self.user})
|
|
|
68f53e0 |
|
|
|
68f53e0 |
self.fd.write(r"""
|
|
|
68f53e0 |
.SH "NAME"
|
|
|
68f53e0 |
%(user)s_u \- \fB%(desc)s\fP - Security Enhanced Linux Policy
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.SH DESCRIPTION
|
|
|
68f53e0 |
|
|
|
68f53e0 |
\fB%(user)s_u\fP is an SELinux User defined in the SELinux
|
|
|
68f53e0 |
policy. SELinux users have default roles, \fB%(user)s_r\fP. The
|
|
|
68f53e0 |
default role has a default type, \fB%(user)s_t\fP, associated with it.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
The SELinux user will usually login to a system with a context that looks like:
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B %(user)s_u:%(user)s_r:%(user)s_u:s0-s0:c0.c1023
|
|
|
68f53e0 |
|
|
|
68f53e0 |
Linux users are automatically assigned an SELinux users at login.
|
|
|
68f53e0 |
Login programs use the SELinux User to assign initial context to the user's shell.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
SELinux policy uses the context to control the user's access.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
By default all users are assigned to the SELinux user via the \fB__default__\fP flag
|
|
|
68f53e0 |
|
|
|
68f53e0 |
On Targeted policy systems the \fB__default__\fP user is assigned to the \fBunconfined_u\fP SELinux user.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
You can list all Linux User to SELinux user mapping using:
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B semanage login -l
|
|
|
68f53e0 |
|
|
|
68f53e0 |
If you wanted to change the default user mapping to use the %(user)s_u user, you would execute:
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B semanage login -m -s %(user)s_u __default__
|
|
|
68f53e0 |
|
|
|
68f53e0 |
""" % {'desc': self.desc, 'type':self.type, 'user':self.user})
|
|
|
68f53e0 |
|
|
|
68f53e0 |
if "login_userdomain" in self.attributes and "login_userdomain" in all_attributes:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
If you want to map the one Linux user (joe) to the SELinux user %(user)s, you would execute:
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B $ semanage login -a -s %(user)s_u joe
|
|
|
68f53e0 |
|
|
|
68f53e0 |
""" % {'user':self.user})
|
|
|
68f53e0 |
|
|
|
68f53e0 |
def can_sudo(self):
|
|
|
68f53e0 |
sudotype = "%s_sudo_t" % self.user
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
.SH SUDO
|
|
|
68f53e0 |
""")
|
|
|
68f53e0 |
if sudotype in types:
|
|
|
68f53e0 |
role = self.user + "_r"
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
The SELinux user %(user)s can execute sudo.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
You can set up sudo to allow %(user)s to transition to an administrative domain:
|
|
|
68f53e0 |
|
|
|
68f53e0 |
Add one or more of the following record to sudoers using visudo.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
""" % { 'user':self.user } )
|
|
|
68f53e0 |
for adminrole in role_allows[role]:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
USERNAME ALL=(ALL) ROLE=%(admin)s_r TYPE=%(admin)s_t COMMAND
|
|
|
68f53e0 |
.br
|
|
|
68f53e0 |
sudo will run COMMAND as %(user)s_u:%(admin)s_r:%(admin)s_t:LEVEL
|
|
|
68f53e0 |
""" % {'admin':adminrole[:-2], 'user':self.user } )
|
|
|
68f53e0 |
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
You might also need to add one or more of these new roles to your SELinux user record.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
List the SELinux roles your SELinux user can reach by executing:
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B $ semanage user -l |grep selinux_name
|
|
|
68f53e0 |
|
|
|
68f53e0 |
Modify the roles list and add %(user)s_r to this list.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B $ semanage user -m -R '%(roles)s' %(user)s_u
|
|
|
68f53e0 |
|
|
|
68f53e0 |
For more details you can see semanage man page.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
""" % {'user':self.user, "roles": " ".join([role] + role_allows[role]) } )
|
|
|
68f53e0 |
else:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
The SELinux type %s_t is not allowed to execute sudo.
|
|
|
68f53e0 |
""" % self.user)
|
|
|
68f53e0 |
|
|
|
68f53e0 |
def user_attribute(self):
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
.SH USER DESCRIPTION
|
|
|
68f53e0 |
""")
|
|
|
68f53e0 |
if "unconfined_usertype" in self.attributes:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
The SELinux user %s_u is an unconfined user. It means that a mapped Linux user to this SELinux user is supposed to be allow all actions.
|
|
|
68f53e0 |
""" % self.user)
|
|
|
68f53e0 |
|
|
|
68f53e0 |
if "unpriv_userdomain" in self.attributes:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
The SELinux user %s_u is defined in policy as a unprivileged user. SELinux prevents unprivileged users from doing administration tasks without transitioning to a different role.
|
|
|
68f53e0 |
""" % self.user)
|
|
|
68f53e0 |
|
|
|
68f53e0 |
if "admindomain" in self.attributes:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
The SELinux user %s_u is an admin user. It means that a mapped Linux user to this SELinux user is intended for administrative actions. Usually this is assigned to a root Linux user.
|
|
|
68f53e0 |
""" % self.user)
|
|
|
68f53e0 |
|
|
|
68f53e0 |
def xwindows_login(self):
|
|
|
68f53e0 |
if "x_domain" in all_attributes:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
.SH X WINDOWS LOGIN
|
|
|
68f53e0 |
""")
|
|
|
68f53e0 |
if "x_domain" in self.attributes:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
The SELinux user %s_u is able to X Windows login.
|
|
|
68f53e0 |
""" % self.user)
|
|
|
68f53e0 |
else:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
The SELinux user %s_u is not able to X Windows login.
|
|
|
68f53e0 |
""" % self.user)
|
|
|
68f53e0 |
|
|
|
68f53e0 |
def terminal_login(self):
|
|
|
68f53e0 |
if "login_userdomain" in all_attributes:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
.SH TERMINAL LOGIN
|
|
|
68f53e0 |
""")
|
|
|
68f53e0 |
if "login_userdomain" in self.attributes:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
The SELinux user %s_u is able to terminal login.
|
|
|
68f53e0 |
""" % self.user)
|
|
|
68f53e0 |
else:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
The SELinux user %s_u is not able to terminal login.
|
|
|
68f53e0 |
""" % self.user)
|
|
|
68f53e0 |
|
|
|
68f53e0 |
def booleans(self):
|
|
|
68f53e0 |
self.booltext = ""
|
|
|
68f53e0 |
for b in bools:
|
|
|
68f53e0 |
if b.startswith("allow_user_") is True or \
|
|
|
68f53e0 |
b.startswith("allow_" + self.user + "_") or \
|
|
|
68f53e0 |
b.startswith(self.user + "_") or \
|
|
|
68f53e0 |
b.startswith("user_"):
|
|
|
68f53e0 |
desc = seobject.booleans_dict[b][2][0].lower() + seobject.booleans_dict[b][2][1:]
|
|
|
68f53e0 |
if desc[-1] == ".":
|
|
|
68f53e0 |
desc = desc[:-1]
|
|
|
68f53e0 |
self.booltext += """
|
|
|
68f53e0 |
.PP
|
|
|
68f53e0 |
If you want to %s, you must turn on the %s boolean.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.EX
|
|
|
68f53e0 |
.B setsebool -P %s 1
|
|
|
68f53e0 |
.EE
|
|
|
68f53e0 |
""" % (desc, b, b)
|
|
|
68f53e0 |
|
|
|
68f53e0 |
if self.booltext != "":
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
.SH BOOLEANS
|
|
|
68f53e0 |
SELinux policy is customizable based on least access required. %s policy is extremely flexible and has several booleans that allow you to manipulate the policy and run %s with the tightest access possible.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
""" % (self.type, self.type))
|
|
|
68f53e0 |
|
|
|
68f53e0 |
self.fd.write(self.booltext)
|
|
|
68f53e0 |
|
|
|
68f53e0 |
def network(self):
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
.SH NETWORK
|
|
|
68f53e0 |
""")
|
|
|
68f53e0 |
for net in ("tcp", "udp"):
|
|
|
68f53e0 |
portdict = senetwork.get_network_connect(self.type, net, "name_bind")
|
|
|
68f53e0 |
if len(portdict) > 0:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
.TP
|
|
|
68f53e0 |
The SELinux user %s_u is able to listen on the following %s ports.
|
|
|
68f53e0 |
""" % (self.user, net))
|
|
|
68f53e0 |
for p in portdict:
|
|
|
68f53e0 |
for recs in portdict[p]:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
.B %s
|
|
|
68f53e0 |
""" % recs)
|
|
|
68f53e0 |
portdict = senetwork.get_network_connect(self.type, "tcp", "name_connect")
|
|
|
68f53e0 |
if len(portdict) > 0:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
.TP
|
|
|
68f53e0 |
The SELinux user %s_u is able to connect to the following tcp ports.
|
|
|
68f53e0 |
""" % (self.user))
|
|
|
68f53e0 |
for p in portdict:
|
|
|
68f53e0 |
for recs in portdict[p]:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
.B %s
|
|
|
68f53e0 |
""" % recs)
|
|
|
68f53e0 |
|
|
|
68f53e0 |
def home_exec(self):
|
|
|
68f53e0 |
permlist = setools.sesearch([setools.ALLOW],{'scontext':self.type,'tcontext':'user_home_type', 'class':'file', 'permlist':['ioctl', 'read', 'getattr', 'execute', 'execute_no_trans', 'open']})
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
.SH HOME_EXEC
|
|
|
68f53e0 |
""" )
|
|
|
68f53e0 |
if permlist is not None:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
The SELinux user %s_u is able execute home content files.
|
|
|
68f53e0 |
""" % self.user)
|
|
|
68f53e0 |
|
|
|
68f53e0 |
else:
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
The SELinux user %s_u is not able execute home content files.
|
|
|
68f53e0 |
""" % self.user)
|
|
|
68f53e0 |
|
|
|
68f53e0 |
def transitions(self):
|
|
|
68f53e0 |
self.fd.write(r"""
|
|
|
68f53e0 |
.SH TRANSITIONS
|
|
|
68f53e0 |
|
|
|
68f53e0 |
Three things can happen when %(type)s attempts to execute a program.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
\fB1.\fP SELinux Policy can deny %(type)s from executing the program.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.TP
|
|
|
68f53e0 |
|
|
|
68f53e0 |
\fB2.\fP SELinux Policy can allow %(type)s to execute the program in the current user type.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
Execute the following to see the types that the SELinux user %(type)s can execute without transitioning:
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B sesearch -A -s %(type)s -c file -p execute_no_trans
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.TP
|
|
|
68f53e0 |
|
|
|
68f53e0 |
\fB3.\fP SELinux can allow %(type)s to execute the program and transition to a new type.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
Execute the following to see the types that the SELinux user %(type)s can execute and transition:
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B $ sesearch -A -s %(type)s -c process -p transition
|
|
|
68f53e0 |
|
|
|
68f53e0 |
""" % {'user':self.user, 'type':self.type})
|
|
|
68f53e0 |
|
|
|
68f53e0 |
def role_header(self):
|
|
|
68f53e0 |
self.fd.write('.TH "%(user)s_selinux" "8" "%(user)s" "mgrepl@redhat.com" "%(user)s SELinux Policy documentation"'
|
|
|
68f53e0 |
% {'user':self.user})
|
|
|
68f53e0 |
|
|
|
68f53e0 |
self.fd.write(r"""
|
|
|
68f53e0 |
.SH "NAME"
|
|
|
68f53e0 |
%(user)s_r \- \fB%(desc)s\fP - Security Enhanced Linux Policy
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.SH DESCRIPTION
|
|
|
68f53e0 |
|
|
|
68f53e0 |
SELinux supports Roles Based Access Control, some Linux roles are login roles, while other roles need to be transition to.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
Note: The examples in the man page will user the staff_u user.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
Non login roles are usually used for administrative tasks.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
Roles usually have default types assigned to them.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
The default type for the %(user)s_r role is %(user)s_t.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
You can use the
|
|
|
68f53e0 |
.B newrole
|
|
|
68f53e0 |
program to transition directly to this role.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B newrole -r %(user)s_r -t %(user)s_t
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B sudo
|
|
|
68f53e0 |
can also be setup to transition to this role using the visudo command.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
USERNAME ALL=(ALL) ROLE=%(user)s_r TYPE=%(user)s_t COMMAND
|
|
|
68f53e0 |
.br
|
|
|
68f53e0 |
sudo will run COMMAND as staff_u:%(user)s_r:%(user)s_t:LEVEL
|
|
|
68f53e0 |
|
|
|
68f53e0 |
If you want to use a non login role, you need to make sure the SELinux user you are using can reach this role.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
You can see all of the assigned SELinux roles using the following
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B semanage user -l
|
|
|
68f53e0 |
|
|
|
68f53e0 |
If you wanted to add %(user)s_r to the staff_u user, you would execute:
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B $ semanage user -m -R 'staff_r %(user)s_r' staff_u
|
|
|
68f53e0 |
|
|
|
68f53e0 |
""" % {'desc': self.desc, 'user':self.user})
|
|
|
68f53e0 |
troles = []
|
|
|
68f53e0 |
for i in role_allows:
|
|
|
68f53e0 |
if self.user +"_r" in role_allows[i]:
|
|
|
68f53e0 |
troles.append(i)
|
|
|
68f53e0 |
if len(troles) > 0:
|
|
|
68f53e0 |
plural = ""
|
|
|
68f53e0 |
if len(troles) > 1:
|
|
|
68f53e0 |
plural = "s"
|
|
|
68f53e0 |
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
|
|
|
68f53e0 |
SELinux policy also controls which roles can transition to a different role.
|
|
|
68f53e0 |
You can list these rules using the following command.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B sesearch --role_allow
|
|
|
68f53e0 |
|
|
|
68f53e0 |
SELinux policy allows the %s role%s can transition to the %s_r role.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
""" % (", ".join(troles), plural, self.user))
|
|
|
68f53e0 |
|
|
|
68f53e0 |
def footer(self):
|
|
|
68f53e0 |
self.fd.write("""
|
|
|
68f53e0 |
.SH "COMMANDS"
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B semanage login
|
|
|
68f53e0 |
can also be used to manipulate the Linux User to SELinux User mappings
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B semanage user
|
|
|
68f53e0 |
can also be used to manipulate SELinux user definitions.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.B system-config-selinux
|
|
|
68f53e0 |
is a GUI tool available to customize SELinux policy settings.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.SH AUTHOR
|
|
|
68f53e0 |
This manual page was autogenerated by genuserman.py.
|
|
|
68f53e0 |
|
|
|
68f53e0 |
.SH "SEE ALSO"
|
|
|
68f53e0 |
selinux(8), semanage(8).
|
|
|
68f53e0 |
""")
|
|
|
68f53e0 |
|
|
|
68f53e0 |
for r in roles:
|
|
|
68f53e0 |
ManPage(r)
|