#! /usr/bin/env python # Copyright (C) 2004 Tresys Technology, LLC # see file 'COPYING' for use and warranty information # # genhomedircon - this script is used to generate file context # configuration entries for user home directories based on their # default roles and is run when building the policy. Specifically, we # replace HOME_ROOT, HOME_DIR, and ROLE macros in .fc files with # generic and user-specific values. # # Based off original script by Dan Walsh, # # ASSUMPTIONS: # # The file CONTEXTDIR/files/homedir_template exists. This file is used to # set up the home directory context for each real user. # # If a user has more than one role in CONTEXTDIR/local.users, genhomedircon uses # the first role in the list. # # If a user is not listed in CONTEXTDIR/local.users, he will default to user_u, role user # # "Real" users (as opposed to system users) are those whose UID is greater than # or equal STARTING_UID (usually 500) and whose login is not a member of # EXCLUDE_LOGINS. Users who are explicitly defined in CONTEXTDIR/local.users # are always "real" (including root, in the default configuration). # # import commands, sys, os, pwd, string rhplPath="/usr/lib/python%d.%d/site-packages/rhpl" % (sys.version_info[0], sys.version_info[1]) if not rhplPath in sys.path: sys.path.append(rhplPath) rhplPath="/usr/lib64/python%d.%d/site-packages/rhpl" % (sys.version_info[0], sys.version_info[1]) if not rhplPath in sys.path: sys.path.append(rhplPath) from Conf import * EXCLUDE_LOGINS=["/sbin/nologin", "/bin/false"] SELINUXDIR="/etc/selinux/" SELINUXCONFIG=SELINUXDIR+"config" CONTEXTDIR="/contexts" FILECONTEXTDIR=CONTEXTDIR+"/files" HOMEDIRTEMPLATE="/homedir_template" USERSFILE="/users/local.users" def getStartingUID(): conf=Conf("/etc/login.defs") while conf.findnextcodeline(): if conf.getfields()[0] == "UID_MIN": return int(conf.getfields()[1]) conf.nextline() return 500 def getDefaultHomeDir(): conf=ConfShellVar("/etc/default/useradd") if conf.has_key("HOME"): return conf["HOME"] else: return "/home" def getHomeDirs(): ulist = pwd.getpwall() homedirs = [] homedirs.append(getDefaultHomeDir()) starting_uid=getStartingUID() for u in ulist: if u[2] >= starting_uid and \ not u[6] in EXCLUDE_LOGINS and \ u[5] != "/" and \ string.count(u[5], "/") > 1: homedir = u[5][:string.rfind(u[5], "/")] if not homedir in homedirs: homedirs.append(homedir) homedirs.sort() return homedirs def usage(error = ""): if error != "": sys.stderr.write("%s\n" % (error,)) sys.stderr.write("Usage: %s \n" % sys.argv[0]) sys.stderr.flush() sys.exit(1) def errorExit(error): sys.stderr.write("%s exiting for: " % sys.argv[0]) sys.stderr.write("%s\n" % error) sys.stderr.flush() sys.exit(1) class selinuxConfig: def __init__(self): self.type="targeted" self.types=[] if os.access(SELINUXDIR, os.F_OK) == 0: #File doesn't exist. return return None conf=ConfShellVar(SELINUXCONFIG) if conf.has_key("SELINUXTYPE"): self.type=conf.vars["SELINUXTYPE"] def getSelinuxType(self): return self.type def getFileContextDir(self): return SELINUXDIR+self.getSelinuxType()+FILECONTEXTDIR def getContextDir(self): return SELINUXDIR+self.getSelinuxType()+CONTEXTDIR def getHomeDirTemplate(self): return self.getFileContextDir()+HOMEDIRTEMPLATE def getHomeRootContext(self): rc=commands.getstatusoutput("grep HOME_ROOT %s | sed -e \"s|^HOME_ROOT|%s|\"" % ( self.getHomeDirTemplate(), getDefaultHomeDir())) if rc[0] == 0: return rc[1] else: errorExit(string.join("sed error ", rc[1])) def getUsersFile(self): return SELINUXDIR+self.getSelinuxType()+USERSFILE def heading(self): ret = "\n#\n#\n# User-specific file contexts, generated via %s\n" % sys.argv[0] ret += "# edit %s to change file_context\n#\n#\n" % self.getUsersFile() return ret def getUsers(self): rc = commands.getstatusoutput("grep ^user %s" % self.getUsersFile()) udict = {} prefs = {} if rc[0] == 0: ulist = rc[1].strip().split("\n") for u in ulist: user = u.split() try: if user[1] == "user_u" or user[1] == "system_u": continue # !!! chooses first role in the list to use in the file context !!! role = user[3] if role == "{": role = user[4] role = role.split("_r")[0] home = pwd.getpwnam(user[1])[5] if home == "/": continue prefs = {} prefs["role"] = role prefs["home"] = home udict[user[1]] = prefs except KeyError: sys.stderr.write("The user \"%s\" is not present in the passwd file, skipping...\n" % (user[1],)) return udict def getHomeDirContext(self, user, home, role): ret="\n\n#\n# Context for user %s\n#\n\n" % user rc=commands.getstatusoutput("grep -e '^HOME_DIR' %s | sed -e 's|HOME_DIR|%s|' -e 's/ROLE/%s/' -e 's/system_u/%s/'" % (self.getHomeDirTemplate(), home, role, user)) return ret + rc[1] def genHomeDirContext(self): users = self.getUsers() ret="" # Fill in HOME and ROLE for users that are defined for u in users.keys(): ret += self.getHomeDirContext (u, users[u]["home"], users[u]["role"]) return ret def genoutput(self): ret= self.heading() ret += self.getHomeRootContext() for h in getHomeDirs(): ret += self.getHomeDirContext ("user_u" , h, "user") ret += self.genHomeDirContext() return ret def printout(self): print self.genoutput() def write(self): fd = open(self.getFileContextDir()+"/file_context.homedirs", "w") fd.write(self.genoutput()) fd.close() # # This script will generate home dir file context # based off the homedir_template file, entries in the password file, and # try: selconf=selinuxConfig() selconf.write() except ValueError, error: errorExit(string.join("ValueError ", error)) except IndexError, error: errorExit("IndexError")