Merge: Verify permissions of preflight and postflight scripts are secure before; skip execution of insecure skips but continue Munki run.

git-svn-id: http://munki.googlecode.com/svn/trunk@738 a4e17f2e-e282-11dd-95e1-755cbddbdd66
This commit is contained in:
Justin McWilliams
2010-09-09 21:42:27 +00:00
parent 4f74f2806f
commit 1ca7fc80e8
2 changed files with 60 additions and 2 deletions
+8 -1
View File
@@ -278,13 +278,20 @@ def runPreOrPostFlightScript(script, runtype='custom'):
Args:
script: string path to the pre/postflight script to execute.
runtype: string mode managedsoftwareupdate was executed with.
For more info see
For more info see
http://code.google.com/p/munki/wiki/PreflightAndPostflightScripts
Returns:
Integer exit status from preflight or postflight script.
"""
if os.path.exists(script):
try:
munkicommon.verifyFileOnlyWritableByMunkiAndRoot(script)
except munkicommon.VerifyFilePermissionsError, e:
msg = ("Skipping execution due to failed file permissions "
"verification: %s\n%s" % (script, str(e)))
munkicommon.display_warning(msg)
return 0 # preflight/postflight does not get run
if os.access(script, os.X_OK):
munkicommon.log('Running %s with runtype: %s...' %
(script, runtype))
+52 -1
View File
@@ -25,6 +25,7 @@ Common functions used by the munki tools.
import hashlib
import os
import shutil
import stat
import subprocess
import sys
import tempfile
@@ -37,6 +38,18 @@ import munkistatus
import FoundationPlist
class Error(Exception):
"""Class for domain specific exceptions."""
class VerifyFilePermissionsError(Error):
"""There was an error verifying file permissions."""
class InsecureFilePermissionsError(VerifyFilePermissionsError):
"""The permissions of the specified file are insecure."""
def get_version():
'''Returns version of munkitools'''
return "0.6.0 Build 709"
@@ -973,7 +986,7 @@ def getInstalledPackageVersion(pkgid):
try:
plist = FoundationPlist.readPlistFromString(out)
except FoundationPlist.NSPropertyListSerializationException:
pass
pass
else:
foundbundleid = plist.get("pkgid")
foundvers = plist.get("pkg-version","0.0.0.0.0")
@@ -1128,6 +1141,44 @@ def getPackageMetaData(pkgitem):
# some utility functions
def verifyFileOnlyWritableByMunkiAndRoot(file_path):
"""
Check the permissions on a given file path; fail if owner or group
does not match the munki process (default: root/admin) or the group is not
"wheel", or if other users are able to write to the file. This prevents
escalated execution of arbitrary code.
Args:
file_path: str path of file to verify permissions on.
Raises:
VerifyFilePermissionsError: there was an error verifying file permissions.
InsecureFilePermissionsError: file permissions were found to be insecure.
"""
try:
file_stat = os.stat(file_path)
except OSError, e:
raise VerifyFilePermissionsError(
'%s does not exist. \n %s' % (file_path, str(e)))
try:
# verify the munki process uid matches the file owner uid.
if os.geteuid() != file_stat.st_uid:
raise InsecureFilePermissionsError(
'owner does not match munki process!')
# verify the munki process gid matches the file owner gid, or the file
# owner gid is 80 (which is the admin group root is a member of).
elif os.getegid() != file_stat.st_gid and file_stat.st_gid != 80:
raise InsecureFilePermissionsError(
'group does not match munki process!')
# verify other users cannot write to the file.
elif file_stat.st_mode & stat.S_IWOTH!= 0:
raise InsecureFilePermissionsError('world writable!')
except InsecureFilePermissionsError, e:
raise InsecureFilePermissionsError(
'%s is not secure! %s' % (file_path, e.args[0]))
def getAvailableDiskSpace(volumepath="/"):
'''Returns available diskspace in KBytes.'''
cmd = ["/usr/sbin/diskutil", "info", "-plist", volumepath]