Chris PeBenito 17de1b7
#! /usr/bin/env python
Chris PeBenito 17de1b7
# Copyright (C) 2004 Tresys Technology, LLC
Chris PeBenito 17de1b7
# see file 'COPYING' for use and warranty information
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
# genhomedircon - this script is used to generate file context
Chris PeBenito 17de1b7
# configuration entries for user home directories based on their
Chris PeBenito 17de1b7
# default roles and is run when building the policy. Specifically, we
Chris PeBenito 17de1b7
# replace HOME_ROOT, HOME_DIR, and ROLE macros in .fc files with
Chris PeBenito 17de1b7
# generic and user-specific values.
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
# Based off original script by Dan Walsh, <dwalsh@redhat.com>
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
# ASSUMPTIONS:
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
# The file CONTEXTDIR/files/homedir_template exists.  This file is used to
Chris PeBenito 17de1b7
# set up the home directory context for each real user.
Chris PeBenito 17de1b7
# 
Chris PeBenito 17de1b7
# If a user has more than one role in CONTEXTDIR/local.users, genhomedircon uses
Chris PeBenito 17de1b7
#  the first role in the list.
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
# If a user is not listed in CONTEXTDIR/local.users, he will default to user_u, role user
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
# "Real" users (as opposed to system users) are those whose UID is greater than
Chris PeBenito 17de1b7
#  or equal STARTING_UID (usually 500) and whose login is not a member of
Chris PeBenito 17de1b7
#  EXCLUDE_LOGINS.  Users who are explicitly defined in CONTEXTDIR/local.users
Chris PeBenito 17de1b7
#  are always "real" (including root, in the default configuration).
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
#  
Chris PeBenito 17de1b7
# Old ASSUMPTIONS:
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
# If a user has more than one role in FILECONTEXTDIR/users, genhomedircon uses
Chris PeBenito 17de1b7
#  the first role in the list.
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
# If a user is not listed in FILECONTEXTDIR/users, genhomedircon assumes that
Chris PeBenito 17de1b7
#  the user's home dir will be found in one of the HOME_ROOTs.
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
# "Real" users (as opposed to system users) are those whose UID is greater than
Chris PeBenito 17de1b7
#  or equal STARTING_UID (usually 500) and whose login is not a member of
Chris PeBenito 17de1b7
#  EXCLUDE_LOGINS.  Users who are explicitly defined in FILECONTEXTDIR/users
Chris PeBenito 17de1b7
#  are always "real" (including root, in the default configuration).
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
import commands, sys, os, pwd, string, getopt, re
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
EXCLUDE_LOGINS=["/sbin/nologin", "/bin/false"]
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
def getStartingUID():
Chris PeBenito 17de1b7
	starting_uid = sys.maxint
Chris PeBenito 17de1b7
	rc=commands.getstatusoutput("grep -h '^UID_MIN' /etc/login.defs")
Chris PeBenito 17de1b7
	if rc[0] == 0:
Chris PeBenito 17de1b7
		uid_min = re.sub("^UID_MIN[^0-9]*", "", rc[1])
Chris PeBenito 17de1b7
		#stip any comment from the end of the line
Chris PeBenito 17de1b7
		uid_min = uid_min.split("#")[0]
Chris PeBenito 17de1b7
		uid_min = uid_min.strip()
Chris PeBenito 17de1b7
		if int(uid_min) < starting_uid:
Chris PeBenito 17de1b7
			starting_uid = int(uid_min)
Chris PeBenito 17de1b7
	rc=commands.getstatusoutput("grep -h '^LU_UIDNUMBER' /etc/libuser.conf")
Chris PeBenito 17de1b7
	if rc[0] == 0:
Chris PeBenito 17de1b7
		lu_uidnumber = re.sub("^LU_UIDNUMBER[^0-9]*", "", rc[1])
Chris PeBenito 17de1b7
		#stip any comment from the end of the line
Chris PeBenito 17de1b7
		lu_uidnumber = re.sub("[ \t].*", "", lu_uidnumber)
Chris PeBenito 17de1b7
		lu_uidnumber = lu_uidnumber.split("#")[0]
Chris PeBenito 17de1b7
		lu_uidnumber = lu_uidnumber.strip()
Chris PeBenito 17de1b7
		if int(lu_uidnumber) < starting_uid:
Chris PeBenito 17de1b7
			starting_uid = int(lu_uidnumber)
Chris PeBenito 17de1b7
	if starting_uid == sys.maxint:
Chris PeBenito 17de1b7
		starting_uid = 500
Chris PeBenito 17de1b7
	return starting_uid
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
#############################################################################
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
# This section is just for backwards compatability
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
#############################################################################
Chris PeBenito 17de1b7
def getPrefixes():
Chris PeBenito 17de1b7
	ulist = pwd.getpwall()
Chris PeBenito 17de1b7
	STARTING_UID=getStartingUID()
Chris PeBenito 17de1b7
	prefixes = {}
Chris PeBenito 17de1b7
	for u in ulist:
Chris PeBenito 17de1b7
		if u[2] >= STARTING_UID and \
Chris PeBenito 17de1b7
				not u[6] in EXCLUDE_LOGINS and \
Chris PeBenito 17de1b7
				u[5] != "/" and \
Chris PeBenito 17de1b7
				string.count(u[5], "/") > 1:
Chris PeBenito 17de1b7
			prefix = u[5][:string.rfind(u[5], "/")]
Chris PeBenito 17de1b7
			if not prefixes.has_key(prefix):
Chris PeBenito 17de1b7
				prefixes[prefix] = ""
Chris PeBenito 17de1b7
	return prefixes
Chris PeBenito 17de1b7
 
Chris PeBenito 17de1b7
def getUsers(filecontextdir):
Chris PeBenito 17de1b7
	rc = commands.getstatusoutput("grep ^user %s/users" % filecontextdir)
Chris PeBenito 17de1b7
	udict = {}
Chris PeBenito 17de1b7
	if rc[0] == 0:
Chris PeBenito 17de1b7
		ulist = rc[1].strip().split("\n")
Chris PeBenito 17de1b7
		for u in ulist:
Chris PeBenito 17de1b7
			user = u.split()
Chris PeBenito 17de1b7
			try:
Chris PeBenito 17de1b7
				if user[1] == "user_u" or user[1] == "system_u":
Chris PeBenito 17de1b7
					continue
Chris PeBenito 17de1b7
				# !!! chooses first role in the list to use in the file context !!!
Chris PeBenito 17de1b7
				role = user[3]
Chris PeBenito 17de1b7
				if role == "{":
Chris PeBenito 17de1b7
					role = user[4]
Chris PeBenito 17de1b7
				role = role.split("_r")[0]
Chris PeBenito 17de1b7
				home = pwd.getpwnam(user[1])[5]
Chris PeBenito 17de1b7
				if home == "/":
Chris PeBenito 17de1b7
					continue
Chris PeBenito 17de1b7
				prefs = {}
Chris PeBenito 17de1b7
				prefs["role"] = role
Chris PeBenito 17de1b7
				prefs["home"] = home
Chris PeBenito 17de1b7
				udict[user[1]] = prefs
Chris PeBenito 17de1b7
			except KeyError:
Chris PeBenito 17de1b7
				sys.stderr.write("The user \"%s\" is not present in the passwd file, skipping...\n" % user[1])
Chris PeBenito 17de1b7
	return udict
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
def update(filecontext, user, prefs):
Chris PeBenito 17de1b7
	rc=commands.getstatusoutput("grep -h '^HOME_DIR' %s | grep -v vmware | sed -e 's|HOME_DIR|%s|' -e 's/ROLE/%s/' -e 's/system_u/%s/'" % (filecontext, prefs["home"], prefs["role"], user))
Chris PeBenito 17de1b7
	if rc[0] == 0:
Chris PeBenito 17de1b7
		print rc[1]
Chris PeBenito 17de1b7
	else:
Chris PeBenito 17de1b7
		errorExit(string.join("grep/sed error ", rc[1]))
Chris PeBenito 17de1b7
	return rc
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
def oldgenhomedircon(filecontextdir, filecontext):
Chris PeBenito 17de1b7
	sys.stderr.flush()
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	if os.path.isdir(filecontextdir) == 0:
Chris PeBenito 17de1b7
		sys.stderr.write("New usage is the following\n")
Chris PeBenito 17de1b7
		usage()
Chris PeBenito 17de1b7
        #We are going to define home directory used by libuser and show-utils as a home directory root
Chris PeBenito 17de1b7
        prefixes = {}
Chris PeBenito 17de1b7
        rc=commands.getstatusoutput("grep -h '^HOME' /etc/default/useradd")
Chris PeBenito 17de1b7
        if rc[0] == 0:
Chris PeBenito 17de1b7
                homedir = rc[1].split("=")[1]
Chris PeBenito 17de1b7
                homedir = homedir.split("#")[0]
Chris PeBenito 17de1b7
                homedir = homedir.strip()
Chris PeBenito 17de1b7
                if not prefixes.has_key(homedir):
Chris PeBenito 17de1b7
                        prefixes[homedir] = ""
Chris PeBenito 17de1b7
        else:
Chris PeBenito 17de1b7
                #rc[0] == 256 means the file was there, we read it, but the grep didn't match
Chris PeBenito 17de1b7
                if rc[0] != 256:
Chris PeBenito 17de1b7
                        sys.stderr.write("%s\n" % rc[1])
Chris PeBenito 17de1b7
                        sys.stderr.write("You do not have access to /etc/default/useradd HOME=\n")
Chris PeBenito 17de1b7
                        sys.stderr.flush()
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
        rc=commands.getstatusoutput("grep -h '^LU_HOMEDIRECTORY' /etc/libuser.conf")
Chris PeBenito 17de1b7
        if rc[0] == 0:
Chris PeBenito 17de1b7
                homedir = rc[1].split("=")[1]
Chris PeBenito 17de1b7
                homedir = homedir.split("#")[0]
Chris PeBenito 17de1b7
                homedir = homedir.strip()
Chris PeBenito 17de1b7
                homedir = re.sub(r"[^/a-zA-Z0-9].*$", "", homedir)
Chris PeBenito 17de1b7
                if not prefixes.has_key(homedir):
Chris PeBenito 17de1b7
                        prefixes[homedir] = ""
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
        #the idea is that we need to find all of the home_root_t directories we do this by just accepting
Chris PeBenito 17de1b7
        #any default home directory defined by either /etc/libuser.conf or /etc/default/useradd
Justin P. Mattock d5932a6
        #we then get the potential home directory roots from /etc/passwd or nis or wherever and look at
Chris PeBenito 17de1b7
        #the defined homedir for all users with UID > STARTING_UID.  This list of possible root homedirs
Chris PeBenito 17de1b7
        #is then checked to see if it has an explicite context defined in the file_contexts.  Explicit
Chris PeBenito 17de1b7
        #is any regex that would match it which does not end with .*$ or .+$ since those are general
Chris PeBenito 17de1b7
        #recursive matches.  We then take any regex which ends with [pattern](/.*)?$ and just check against
Chris PeBenito 17de1b7
        #[pattern]
Chris PeBenito 17de1b7
        potential_prefixes = getPrefixes()
Chris PeBenito 17de1b7
        prefix_regex = {}
Chris PeBenito 17de1b7
        #this works by grepping the file_contexts for
Chris PeBenito 17de1b7
        # 1. ^/ makes sure this is not a comment
Chris PeBenito 17de1b7
        # 2. prints only the regex in the first column first cut on \t then on space
Chris PeBenito 17de1b7
        rc=commands.getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1 -d \" \" " %  (sys.argv[2]) )
Chris PeBenito 17de1b7
        if rc[0] == 0:
Chris PeBenito 17de1b7
                prefix_regex = rc[1].split("\n")
Chris PeBenito 17de1b7
        else:
Chris PeBenito 17de1b7
                sys.stderr.write("%s\n" % rc[1])
Chris PeBenito 17de1b7
                sys.stderr.write("You do not have access to grep/cut/the file contexts\n")
Chris PeBenito 17de1b7
                sys.stderr.flush()
Chris PeBenito 17de1b7
        for potential in potential_prefixes.keys():
Chris PeBenito 17de1b7
                addme = 1
Chris PeBenito 17de1b7
                for regex in prefix_regex:
Chris PeBenito 17de1b7
                        #match a trailing (/*)? which is actually a bug in rpc_pipefs
Chris PeBenito 17de1b7
                        regex = re.sub("\(/\*\)\?$", "", regex)
Chris PeBenito 17de1b7
                        #match a trailing .+
Chris PeBenito 17de1b7
                        regex = re.sub("\.+$", "", regex)
Chris PeBenito 17de1b7
                        #match a trailing .*
Chris PeBenito 17de1b7
                        regex = re.sub("\.\*$", "", regex)
Chris PeBenito 17de1b7
                        #strip a (/.*)? which matches anything trailing to a /*$ which matches trailing /'s
Chris PeBenito 17de1b7
                        regex = re.sub("\(\/\.\*\)\?", "", regex)
Chris PeBenito 17de1b7
                        regex = regex + "/*$"
Chris PeBenito 17de1b7
                        if re.search(regex, potential, 0):
Chris PeBenito 17de1b7
                                addme = 0
Chris PeBenito 17de1b7
                if addme == 1:
Chris PeBenito 17de1b7
                        if not prefixes.has_key(potential):
Chris PeBenito 17de1b7
                                prefixes[potential] = ""
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
        if prefixes.__eq__({}):
Chris PeBenito 17de1b7
                sys.stderr.write("LU_HOMEDIRECTORY not set in /etc/libuser.conf\n")
Chris PeBenito 17de1b7
                sys.stderr.write("HOME= not set in /etc/default/useradd\n")
Chris PeBenito 17de1b7
                sys.stderr.write("And no users with a reasonable homedir found in passwd/nis/ldap/etc...\n")
Chris PeBenito 17de1b7
                sys.stderr.write("Assuming /home is the root of home directories\n")
Chris PeBenito 17de1b7
                sys.stderr.flush()
Chris PeBenito 17de1b7
                prefixes["/home"] = ""
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	# There may be a more elegant sed script to expand a macro to multiple lines, but this works
Chris PeBenito 17de1b7
	sed_root = "h; s|^HOME_ROOT|%s|" % (string.join(prefixes.keys(), "|; p; g; s|^HOME_ROOT|"),)
Chris PeBenito 17de1b7
	sed_dir = "h; s|^HOME_DIR|%s/[^/]+|; s|ROLE_|user_|" % (string.join(prefixes.keys(), "/[^/]+|; s|ROLE_|user_|; p; g; s|^HOME_DIR|"),)
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	# Fill in HOME_ROOT, HOME_DIR, and ROLE for users not explicitly defined in /etc/security/selinux/src/policy/users
Chris PeBenito 17de1b7
	rc=commands.getstatusoutput("sed -e \"/^HOME_ROOT/{%s}\" -e \"/^HOME_DIR/{%s}\" %s" % (sed_root, sed_dir, filecontext))
Chris PeBenito 17de1b7
	if rc[0] == 0:
Chris PeBenito 17de1b7
		print rc[1]
Chris PeBenito 17de1b7
	else:
Chris PeBenito 17de1b7
		errorExit(string.join("sed error ", rc[1]))
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	users = getUsers(filecontextdir)
Chris PeBenito 17de1b7
	print "\n#\n# User-specific file contexts\n#\n"
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	# Fill in HOME and ROLE for users that are defined
Chris PeBenito 17de1b7
	for u in users.keys():
Chris PeBenito 17de1b7
		update(filecontext, u, users[u]) 
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
#############################################################################
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
# End of backwards compatability section
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
#############################################################################
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
def getDefaultHomeDir():
Chris PeBenito 17de1b7
	ret = []
Chris PeBenito 17de1b7
	rc=commands.getstatusoutput("grep -h '^HOME' /etc/default/useradd")
Chris PeBenito 17de1b7
	if rc[0] == 0:
Chris PeBenito 17de1b7
		homedir = rc[1].split("=")[1]
Chris PeBenito 17de1b7
		homedir = homedir.split("#")[0]
Chris PeBenito 17de1b7
		homedir = homedir.strip()
Chris PeBenito 17de1b7
		if not homedir in ret:
Chris PeBenito 17de1b7
			ret.append(homedir)
Chris PeBenito 17de1b7
	else:
Chris PeBenito 17de1b7
		#rc[0] == 256 means the file was there, we read it, but the grep didn't match
Chris PeBenito 17de1b7
		if rc[0] != 256:
Chris PeBenito 17de1b7
			sys.stderr.write("%s\n" % rc[1])
Chris PeBenito 17de1b7
			sys.stderr.write("You do not have access to /etc/default/useradd HOME=\n")
Chris PeBenito 17de1b7
			sys.stderr.flush()
Chris PeBenito 17de1b7
	rc=commands.getstatusoutput("grep -h '^LU_HOMEDIRECTORY' /etc/libuser.conf")
Chris PeBenito 17de1b7
	if rc[0] == 0:
Chris PeBenito 17de1b7
		homedir = rc[1].split("=")[1]
Chris PeBenito 17de1b7
		homedir = homedir.split("#")[0]
Chris PeBenito 17de1b7
		homedir = homedir.strip()
Chris PeBenito 17de1b7
		if not homedir in ret:
Chris PeBenito 17de1b7
			ret.append(homedir)
Chris PeBenito 17de1b7
	else:
Chris PeBenito 17de1b7
		#rc[0] == 256 means the file was there, we read it, but the grep didn't match
Chris PeBenito 17de1b7
		if rc[0] != 256:
Chris PeBenito 17de1b7
			sys.stderr.write("%s\n" % rc[1])
Chris PeBenito 17de1b7
			sys.stderr.write("You do not have access to /etc/libuser.conf LU_HOMEDIRECTORY=\n")
Chris PeBenito 17de1b7
			sys.stderr.flush()
Chris PeBenito 17de1b7
	if ret == []:
Chris PeBenito 17de1b7
		ret.append("/home")
Chris PeBenito 17de1b7
	return ret
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
def getSELinuxType(directory):
Chris PeBenito 17de1b7
	rc=commands.getstatusoutput("grep ^SELINUXTYPE= %s/config" % directory)
Chris PeBenito 17de1b7
	if rc[0]==0:
Chris PeBenito 17de1b7
		return rc[1].split("=")[-1].strip()
Chris PeBenito 17de1b7
	return "targeted"
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
def usage(error = ""):
Chris PeBenito 17de1b7
	if error != "":
Chris PeBenito 17de1b7
		sys.stderr.write("%s\n" % error)
Chris PeBenito 17de1b7
	sys.stderr.write("Usage: %s [ -d selinuxdir ] [-n | --nopasswd] [-t selinuxtype ]\n" % sys.argv[0])
Chris PeBenito 17de1b7
	sys.stderr.flush()
Chris PeBenito 17de1b7
	sys.exit(1)
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
def warning(warning = ""):
Chris PeBenito 17de1b7
	sys.stderr.write("%s\n" % warning)
Chris PeBenito 17de1b7
	sys.stderr.flush()
Chris PeBenito 17de1b7
	
Chris PeBenito 17de1b7
def errorExit(error):
Chris PeBenito 17de1b7
	sys.stderr.write("%s exiting for: " % sys.argv[0])
Chris PeBenito 17de1b7
	sys.stderr.write("%s\n" % error)
Chris PeBenito 17de1b7
	sys.stderr.flush()
Chris PeBenito 17de1b7
	sys.exit(1)
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
class selinuxConfig:
Chris PeBenito 17de1b7
	def __init__(self, selinuxdir="/etc/selinux", type="targeted", usepwd=1):
Chris PeBenito 17de1b7
		self.type=type
Chris PeBenito 17de1b7
		self.selinuxdir=selinuxdir +"/"
Chris PeBenito 17de1b7
		self.contextdir="/contexts"
Chris PeBenito 17de1b7
		self.filecontextdir=self.contextdir+"/files"
Chris PeBenito 17de1b7
		self.usepwd=usepwd
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	def getFileContextDir(self):
Chris PeBenito 17de1b7
		return self.selinuxdir+self.type+self.filecontextdir
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	def getFileContextFile(self):
Chris PeBenito 17de1b7
		return self.getFileContextDir()+"/file_contexts"
Chris PeBenito 17de1b7
	
Chris PeBenito 17de1b7
	def getContextDir(self):
Chris PeBenito 17de1b7
		return self.selinuxdir+self.type+self.contextdir
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	def getHomeDirTemplate(self):
Chris PeBenito 17de1b7
		return self.getFileContextDir()+"/homedir_template"
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	def getHomeRootContext(self, homedir):
Chris PeBenito 17de1b7
		rc=commands.getstatusoutput("grep HOME_ROOT  %s | sed -e \"s|^HOME_ROOT|%s|\"" % ( self.getHomeDirTemplate(), homedir))
Chris PeBenito 17de1b7
		if rc[0] == 0:
Chris PeBenito 17de1b7
			return rc[1]+"\n"
Chris PeBenito 17de1b7
		else:
Chris PeBenito 17de1b7
			errorExit(string.join("sed error ", rc[1]))
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	def getUsersFile(self):
Chris PeBenito 17de1b7
		return self.selinuxdir+self.type+"/users/local.users"
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	def getSystemUsersFile(self):
Chris PeBenito 17de1b7
		return self.selinuxdir+self.type+"/users/system.users"
Chris PeBenito 17de1b7
		
Chris PeBenito 17de1b7
	def heading(self):
Chris PeBenito 17de1b7
		ret = "\n#\n#\n# User-specific file contexts, generated via %s\n" % sys.argv[0]
Chris PeBenito 17de1b7
		ret += "# edit %s to change file_context\n#\n#\n" % self.getUsersFile()
Chris PeBenito 17de1b7
		return ret
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	def getUsers(self):
Chris PeBenito 17de1b7
		users=""
Chris PeBenito 17de1b7
		rc = commands.getstatusoutput('grep "^user" %s' % self.getSystemUsersFile())
Chris PeBenito 17de1b7
		if rc[0] == 0:
Chris PeBenito 17de1b7
			users+=rc[1]+"\n"
Chris PeBenito 17de1b7
		rc = commands.getstatusoutput("grep ^user %s" % self.getUsersFile())
Chris PeBenito 17de1b7
		if rc[0] == 0:
Chris PeBenito 17de1b7
			users+=rc[1]
Chris PeBenito 17de1b7
		udict = {}
Chris PeBenito 17de1b7
		prefs = {}
Chris PeBenito 17de1b7
		if users != "":
Chris PeBenito 17de1b7
			ulist = users.split("\n")
Chris PeBenito 17de1b7
			for u in ulist:
Chris PeBenito 17de1b7
				user = u.split()
Chris PeBenito 17de1b7
				try:
Chris PeBenito 17de1b7
					if len(user)==0 or user[1] == "user_u" or user[1] == "system_u":
Chris PeBenito 17de1b7
						continue
Chris PeBenito 17de1b7
					# !!! chooses first role in the list to use in the file context !!!
Chris PeBenito 17de1b7
					role = user[3]
Chris PeBenito 17de1b7
					if role == "{":
Chris PeBenito 17de1b7
						role = user[4]
Chris PeBenito 17de1b7
					role = role.split("_r")[0]
Chris PeBenito 17de1b7
					home = pwd.getpwnam(user[1])[5]
Chris PeBenito 17de1b7
					if home == "/":
Chris PeBenito 17de1b7
						continue
Chris PeBenito 17de1b7
					prefs = {}
Chris PeBenito 17de1b7
					prefs["role"] = role
Chris PeBenito 17de1b7
					prefs["home"] = home
Chris PeBenito 17de1b7
					udict[user[1]] = prefs
Chris PeBenito 17de1b7
				except KeyError:
Chris PeBenito 17de1b7
					sys.stderr.write("The user \"%s\" is not present in the passwd file, skipping...\n" % user[1])
Chris PeBenito 17de1b7
		return udict
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	def getHomeDirContext(self, user, home, role):
Chris PeBenito 17de1b7
		ret="\n\n#\n# Context for user %s\n#\n\n" % user
Chris PeBenito 17de1b7
		rc=commands.getstatusoutput("grep '^HOME_DIR' %s | sed -e 's|HOME_DIR|%s|' -e 's/ROLE/%s/' -e 's/system_u/%s/'" % (self.getHomeDirTemplate(), home, role, user))
Chris PeBenito 17de1b7
		return ret + rc[1] + "\n"
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	def genHomeDirContext(self):
Chris PeBenito 17de1b7
		users = self.getUsers()
Chris PeBenito 17de1b7
		ret=""
Chris PeBenito 17de1b7
		# Fill in HOME and ROLE for users that are defined
Chris PeBenito 17de1b7
		for u in users.keys():
Chris PeBenito 17de1b7
			ret += self.getHomeDirContext (u, users[u]["home"], users[u]["role"])
Chris PeBenito 17de1b7
		return ret+"\n"
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	def checkExists(self, home):
Chris PeBenito 17de1b7
		if commands.getstatusoutput("grep -E '^%s[^[:alnum:]_-]' %s" % (home, self.getFileContextFile()))[0] == 0:
Chris PeBenito 17de1b7
			return 0
Chris PeBenito 17de1b7
		#this works by grepping the file_contexts for
Chris PeBenito 17de1b7
		# 1. ^/ makes sure this is not a comment
Chris PeBenito 17de1b7
		# 2. prints only the regex in the first column first cut on \t then on space
Chris PeBenito 17de1b7
		rc=commands.getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1 -d \" \" " %  self.getFileContextFile() )
Chris PeBenito 17de1b7
		if rc[0] == 0:
Chris PeBenito 17de1b7
			prefix_regex = rc[1].split("\n")
Chris PeBenito 17de1b7
		else:
Chris PeBenito 17de1b7
			sys.stderr.write("%s\n" % rc[1])
Chris PeBenito 17de1b7
			sys.stderr.write("You do not have access to grep/cut/the file contexts\n")
Chris PeBenito 17de1b7
			sys.stderr.flush()
Chris PeBenito 17de1b7
		exists=1
Chris PeBenito 17de1b7
		for regex in prefix_regex:
Chris PeBenito 17de1b7
			#match a trailing (/*)? which is actually a bug in rpc_pipefs
Chris PeBenito 17de1b7
			regex = re.sub("\(/\*\)\?$", "", regex)
Chris PeBenito 17de1b7
			#match a trailing .+
Chris PeBenito 17de1b7
			regex = re.sub("\.+$", "", regex)
Chris PeBenito 17de1b7
			#match a trailing .*
Chris PeBenito 17de1b7
			regex = re.sub("\.\*$", "", regex)
Chris PeBenito 17de1b7
			#strip a (/.*)? which matches anything trailing to a /*$ which matches trailing /'s
Chris PeBenito 17de1b7
			regex = re.sub("\(\/\.\*\)\?", "", regex)
Chris PeBenito 17de1b7
			regex = regex + "/*$"
Chris PeBenito 17de1b7
			if re.search(regex, home, 0):
Chris PeBenito 17de1b7
				exists = 0
Chris PeBenito 17de1b7
				break
Chris PeBenito 17de1b7
		if exists == 1:
Chris PeBenito 17de1b7
			return 1
Chris PeBenito 17de1b7
		else:
Chris PeBenito 17de1b7
			return 0
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	def getHomeDirs(self):
Chris PeBenito 17de1b7
		homedirs = []
Chris PeBenito 17de1b7
		homedirs = homedirs + getDefaultHomeDir()
Chris PeBenito 17de1b7
		starting_uid=getStartingUID()
Chris PeBenito 17de1b7
		if self.usepwd==0:
Chris PeBenito 17de1b7
			return homedirs
Chris PeBenito 17de1b7
		ulist = pwd.getpwall()
Chris PeBenito 17de1b7
		for u in ulist:
Chris PeBenito 17de1b7
			if u[2] >= starting_uid and \
Chris PeBenito 17de1b7
					not u[6] in EXCLUDE_LOGINS and \
Chris PeBenito 17de1b7
					u[5] != "/" and \
Chris PeBenito 17de1b7
					string.count(u[5], "/") > 1:
Chris PeBenito 17de1b7
				homedir = u[5][:string.rfind(u[5], "/")]
Chris PeBenito 17de1b7
				if not homedir in homedirs:
Chris PeBenito 17de1b7
					if self.checkExists(homedir)==0:
Chris PeBenito 17de1b7
						warning("%s is already defined in %s,\n%s will not create a new context." % (homedir, self.getFileContextFile(), sys.argv[0]))
Chris PeBenito 17de1b7
					else:
Chris PeBenito 17de1b7
						homedirs.append(homedir)
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
		homedirs.sort()
Chris PeBenito 17de1b7
		return homedirs
Chris PeBenito 17de1b7
 
Chris PeBenito 17de1b7
	def genoutput(self):
Chris PeBenito 17de1b7
		ret= self.heading()
Chris PeBenito 17de1b7
		for h in self.getHomeDirs():
Chris PeBenito 17de1b7
			ret += self.getHomeDirContext ("user_u" , h+'/[^/]*', "user")
Chris PeBenito 17de1b7
			ret += self.getHomeRootContext(h)
Chris PeBenito 17de1b7
		ret += self.genHomeDirContext()
Chris PeBenito 17de1b7
		return ret
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	def printout(self):
Chris PeBenito 17de1b7
		print self.genoutput()
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	def write(self):
Chris PeBenito 17de1b7
		try:
Chris PeBenito 17de1b7
			fd = open(self.getFileContextDir()+"/file_contexts.homedirs", "w")
Chris PeBenito 17de1b7
			fd.write(self.genoutput())
Chris PeBenito 17de1b7
			fd.close()
Chris PeBenito 17de1b7
		except IOError, error:
Chris PeBenito 17de1b7
			sys.stderr.write("%s: %s\n" % ( sys.argv[0], error ))
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
# This script will generate home dir file context
Chris PeBenito 17de1b7
# based off the homedir_template file, entries in the password file, and
Chris PeBenito 17de1b7
#
Chris PeBenito 17de1b7
try:
Chris PeBenito 17de1b7
	usepwd=1
Chris PeBenito 17de1b7
	directory="/etc/selinux"
Chris PeBenito 17de1b7
	type=None
Chris PeBenito 17de1b7
	gopts, cmds = getopt.getopt(sys.argv[1:], 'nd:t:', ['help',
Chris PeBenito 17de1b7
						'type=',
Chris PeBenito 17de1b7
						'nopasswd',
Chris PeBenito 17de1b7
						'dir='])
Chris PeBenito 17de1b7
	for o,a in gopts:
Chris PeBenito 17de1b7
		if o == '--type' or o == "-t":
Chris PeBenito 17de1b7
			type=a
Chris PeBenito 17de1b7
		if o == '--nopasswd'  or o == "-n":
Chris PeBenito 17de1b7
			usepwd=0
Chris PeBenito 17de1b7
		if o == '--dir'  or o == "-d":
Chris PeBenito 17de1b7
			directory=a
Chris PeBenito 17de1b7
		if o == '--help':
Chris PeBenito 17de1b7
			usage()
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	if type==None:
Chris PeBenito 17de1b7
		type=getSELinuxType(directory)
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	if len(cmds) == 2:
Chris PeBenito 17de1b7
		oldgenhomedircon(cmds[0], cmds[1])
Chris PeBenito 17de1b7
		sys.exit(0)
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
	if len(cmds) != 0:
Chris PeBenito 17de1b7
		usage()
Chris PeBenito 17de1b7
	selconf=selinuxConfig(directory, type, usepwd)
Chris PeBenito 17de1b7
	selconf.write()
Chris PeBenito 17de1b7
Chris PeBenito 17de1b7
except getopt.error, error:
Chris PeBenito 17de1b7
	errorExit(string.join("Options Error ", error))
Chris PeBenito 17de1b7
except ValueError, error:
Chris PeBenito 17de1b7
	errorExit(string.join("ValueError ", error))
Chris PeBenito 17de1b7
except IndexError, error:
Chris PeBenito 17de1b7
	errorExit("IndexError")