reduce font size by one

improve user detection for CryptoBoxRootActions
This commit is contained in:
lars 2007-02-09 19:36:41 +00:00
parent 871fce3f6d
commit d8e0bbf429
3 changed files with 76 additions and 39 deletions

View File

@ -23,12 +23,10 @@
"""module for executing the programs, that need root privileges """module for executing the programs, that need root privileges
Syntax: Syntax:
- program - TODO
- device
- [action]
- [action args]
this script will always return with an exitcode 0 (true), if "check" is the only argument this script will always return with an exitcode 0 (true),
if "check" is the only argument
""" """
__revision__ = "$Id" __revision__ = "$Id"
@ -63,10 +61,10 @@ def checkIfFileIsSafe(fname):
## the override setting may be turned off temporarily to allow unittests ## the override setting may be turned off temporarily to allow unittests
if OVERRIDE_FILECHECK: if OVERRIDE_FILECHECK:
return True return True
## if the real user id is 0 (root), then we do not have to check this, ## if the calling user id is 0 (root), then we do not have to check this,
## as root would be allowed to do this anyway ## as root would be allowed to do this anyway
## this eases testing with a not-installed working copy in a uml environment ## this eases testing with a not-installed working copy in a uml environment
if os.getuid() == 0: if getCallingUserInfo()[1] == 0:
return True return True
props = os.stat(fname) props = os.stat(fname)
## check if it is owned by non-root ## check if it is owned by non-root
@ -84,7 +82,7 @@ def checkIfFileIsSafe(fname):
def checkIfPluginIsValid(plugin): def checkIfPluginIsValid(plugin):
import imp import imp
try: try:
x = imp.load_source("cbox_plugin",plugin) x = imp.load_source("cbox_plugin", plugin)
except (SyntaxError, IOError): except (SyntaxError, IOError):
return False return False
try: try:
@ -114,7 +112,8 @@ def call_plugin(args):
## check if the plugin (and its parents) are only writeable for root ## check if the plugin (and its parents) are only writeable for root
## this can be overridden by OVERRIDE_FILECHECK ## this can be overridden by OVERRIDE_FILECHECK
if not checkIfFileIsSafe(plugin): if not checkIfFileIsSafe(plugin):
raise Exception, "the plugin (%s) is not safe - check its (and its parents') permissions" % plugin raise Exception, "the plugin (%s) is not safe - check its " % plugin \
+ "(and its parents') permissions"
## check if the plugin is a python program, that is marked as a cryptobox plugin ## check if the plugin is a python program, that is marked as a cryptobox plugin
if not checkIfPluginIsValid(plugin): if not checkIfPluginIsValid(plugin):
raise Exception, "the plugin (%s) is not a correctly marked python script" % plugin raise Exception, "the plugin (%s) is not a correctly marked python script" % plugin
@ -135,10 +134,13 @@ def call_event(args):
raise Exception, "could not find executable event script (%s)" % event raise Exception, "could not find executable event script (%s)" % event
## check if the script is valid (the marker file must be in the same directory) ## check if the script is valid (the marker file must be in the same directory)
if not checkIfEventScriptIsValid(event): if not checkIfEventScriptIsValid(event):
raise Exception, "the event script (%s) does not reside in a directory with the marker file (%s) - this is not allowed due to abuse prevention" % (event, EVENT_MARKER) raise Exception, "the event script (%s) does not reside in" % event \
+ "a directory with the marker file (%s) - this " % EVENT_MARKER \
+ "is not allowed due to abuse prevention"
## check if the event (and its parents) are only writeable for root ## check if the event (and its parents) are only writeable for root
if not checkIfFileIsSafe(event): if not checkIfFileIsSafe(event):
raise Exception, "the event (%s) is not safe - check its (and its parents') permissions" % event raise Exception, "the event (%s) is not safe - check its " % event \
+ "(and its parents') permissions"
args.insert(0, event) args.insert(0, event)
proc = subprocess.Popen( proc = subprocess.Popen(
shell = False, shell = False,
@ -156,30 +158,30 @@ def isWriteable(path, force_dev_type=None):
this check works nicely together with "super", as it changes (by default) only this check works nicely together with "super", as it changes (by default) only
the effective uid (not the real uid) the effective uid (not the real uid)
""" """
# first check, if the device/file exists ## first check, if the device/file exists
if not os.path.exists(path): if not os.path.exists(path):
sys.stderr.write("%s does not exist!\n" % path) sys.stderr.write("%s does not exist!\n" % path)
return False return False
# check the type of the path - if necessary ## check the type of the path - if necessary
if (not force_dev_type is None) and \ if (not force_dev_type is None) and \
(force_dev_type != os.stat(path).st_mode % 65536 / 4096): (force_dev_type != os.stat(path).st_mode % 65536 / 4096):
sys.stderr.write("%s does not have the numeric type '%d'!\n" \ sys.stderr.write("%s does not have the numeric type '%d'!\n" \
% (path, force_dev_type)) % (path, force_dev_type))
return False return False
## if root is the (real) user, then it is ok ## retrieve the information for the real user id
if os.getuid() == 0: (trustUserName, trustUID, groupsOfTrustUser) = getCallingUserInfo()
## are we called by the root user? this would be ok
if trustUID == 0:
return True return True
## is the path owned by us? ## is the path owned by us?
if os.stat(path)[4] == os.getuid(): if os.stat(path)[4] == trustUID():
return True return True
# retrieve the information for the real user id ## set the default groups of the caller for the check (restore them later)
(trustUserName, trustUID, groupsOfTrustUser) = getUserInfo(os.getuid())
# set the default groups of the caller for the check (restore them later)
savedGroups = os.getgroups() savedGroups = os.getgroups()
os.setgroups(groupsOfTrustUser) os.setgroups(groupsOfTrustUser)
# check permissions ## check permissions
result = os.access(path, os.W_OK) and os.access(path, os.R_OK) result = os.access(path, os.W_OK) and os.access(path, os.R_OK)
# reset the groups of this process ## reset the groups of this process
os.setgroups(savedGroups) os.setgroups(savedGroups)
return result return result
@ -190,7 +192,8 @@ def run_cryptsetup(args):
@args: list of arguments - they will be treated accordingly to the first element @args: list of arguments - they will be treated accordingly to the first element
of this list (the action)""" of this list (the action)"""
if not args: raise "WrongArguments", "no action for cryptsetup supplied" if not args: raise "WrongArguments", "no action for cryptsetup supplied"
if type(args) != types.ListType: raise "WrongArguments", "invalid arguments supplied: %s" % (args, ) if type(args) != types.ListType:
raise "WrongArguments", "invalid arguments supplied: %s" % (args, )
try: try:
action = args[0] action = args[0]
del args[0] del args[0]
@ -246,15 +249,19 @@ def run_cryptsetup(args):
args = cs_args) args = cs_args)
proc.wait() proc.wait()
## chown the devmapper block device to the cryptobox user ## chown the devmapper block device to the cryptobox user
calling_user = getCallingUserInfo()
if (proc.returncode == 0) and (action == "luksOpen"): if (proc.returncode == 0) and (action == "luksOpen"):
os.chown(os.path.join(os.path.sep, "dev", "mapper", destination), os.getuid(), os.getgid()) os.chown(os.path.join(os.path.sep, "dev", "mapper", destination),
calling_user[1], calling_user[2][0])
return proc.returncode == 0 return proc.returncode == 0
def run_sfdisk(args): def run_sfdisk(sf_args):
"""execute sfdisk for partitioning """execute sfdisk for partitioning
not implemented yet""" not implemented yet
TODO: this is useless, as it is done in root_actions.py of the partition plugin?
"""
print "ok - you are free to call sfdisk ..." print "ok - you are free to call sfdisk ..."
print " not yet implemented ..." print " not yet implemented ..."
return True return True
@ -281,7 +288,8 @@ def run_mount(args):
"""execute mount """execute mount
""" """
if not args: raise "WrongArguments", "no destination for mount supplied" if not args: raise "WrongArguments", "no destination for mount supplied"
if type(args) != types.ListType: raise "WrongArguments", "invalid arguments supplied: %s" % (args, ) if type(args) != types.ListType:
raise "WrongArguments", "invalid arguments supplied: %s" % (args, )
try: try:
device = args[0] device = args[0]
del args[0] del args[0]
@ -294,7 +302,8 @@ def run_mount(args):
raise "WrongArguments", "%s is not a writeable block device" % (device, ) raise "WrongArguments", "%s is not a writeable block device" % (device, )
## check permissions for the mountpoint ## check permissions for the mountpoint
if not isWriteable(destination, DEV_TYPES["dir"]): if not isWriteable(destination, DEV_TYPES["dir"]):
raise "WrongArguments", "the mountpoint (%s) is not writeable" % (destination, ) raise "WrongArguments", "the mountpoint (%s) is not writeable" \
% (destination, )
# check for additional (not allowed) arguments # check for additional (not allowed) arguments
if len(args) != 0: if len(args) != 0:
raise "WrongArguments", "too many arguments for 'mount': %s" % (args, ) raise "WrongArguments", "too many arguments for 'mount': %s" % (args, )
@ -343,7 +352,9 @@ def run_mount(args):
try: try:
os.chown(destination, trustUID, groupsOfTrustUser[0]) os.chown(destination, trustUID, groupsOfTrustUser[0])
except OSError, errMsg: except OSError, errMsg:
sys.stderr.write("could not chown the mount destination (%s) to the specified user (%d/%d): %s\n" % (destination, trustUID, groupsOfTrustUser[0], errMsg)) sys.stderr.write("could not chown the mount destination (%s) " % destination \
+ "to the specified user (%d/%d): " % (trustUID, groupsOfTrustUser[0]) \
+ "%s/n" % str(errMsg))
sys.stderr.write("UID: %d\n" % (os.geteuid(),)) sys.stderr.write("UID: %d\n" % (os.geteuid(),))
return False return False
## BEWARE: it would be nice, if we could restore the previous uid (not euid) but ## BEWARE: it would be nice, if we could restore the previous uid (not euid) but
@ -355,13 +366,15 @@ def run_umount(args):
"""execute mount """execute mount
""" """
if not args: raise "WrongArguments", "no mountpoint for umount supplied" if not args: raise "WrongArguments", "no mountpoint for umount supplied"
if type(args) != types.ListType: raise "WrongArguments", "invalid arguments supplied" if type(args) != types.ListType:
raise "WrongArguments", "invalid arguments supplied"
try: try:
destination = args[0] destination = args[0]
del args[0] del args[0]
# check permissions for the destination # check permissions for the destination
if not isWriteable(os.path.dirname(destination), DEV_TYPES["dir"]): if not isWriteable(os.path.dirname(destination), DEV_TYPES["dir"]):
raise "WrongArguments", "the parent of the mountpoint (%s) is not writeable" % (destination, ) raise "WrongArguments", "the parent of the mountpoint " \
+ "(%s) is not writeable" % (destination, )
if len(args) != 0: raise "WrongArguments", "umount does not allow arguments" if len(args) != 0: raise "WrongArguments", "umount does not allow arguments"
except TypeError: except TypeError:
raise "WrongArguments", "invalid arguments supplied" raise "WrongArguments", "invalid arguments supplied"
@ -379,23 +392,43 @@ def run_umount(args):
return proc.returncode == 0 return proc.returncode == 0
def getCallingUserInfo():
"""return information about the user that was calling this program via "super"
@user: (uid or name)
@return: tuple of (name, uid, (groups))
"""
## are we called via 'super'?
if ("SUPERCMD" in os.environ) and ("USER" in os.environ):
## return the user that was calling super
return getUserInfo(os.environ["USER"])
else:
## return the current user
return getUserInfo(os.getuid())
def getUserInfo(user): def getUserInfo(user):
"""return information about the specified user """return information about the specified user
@user: (uid or name) @user: (uid or name)
@return: tuple of (name, uid, (groups)) @return: tuple of (name, uid, (groups))
""" """
if user is None: raise "KeyError", "no user supplied" if (user is None) or (user == ""):
# first check, if 'user' contains an id - then check for a name raise "KeyError", "no user supplied"
try: ## if a KeyError is raised again in the following lines, then the supplied
## user was invalid
if type(user) is int:
# 'user' is a uid
userinfo = pwd.getpwuid(user) userinfo = pwd.getpwuid(user)
except TypeError: elif type(user) is str:
# if a KeyError is raised again, then the supplied user was invalid # 'user' is a name
userinfo = pwd.getpwnam(user) userinfo = pwd.getpwnam(user)
u_groups = [one_group.gr_gid u_groups = [one_group.gr_gid
for one_group in grp.getgrall() for one_group in grp.getgrall()
if userinfo.pw_name in one_group.gr_mem] if userinfo.pw_name in one_group.gr_mem]
if not userinfo.pw_gid in u_groups: u_groups.append(userinfo.pw_gid) if not userinfo.pw_gid in u_groups:
## put in front of the list
u_groups.insert(0,userinfo.pw_gid)
return (userinfo.pw_name, userinfo.pw_uid, u_groups) return (userinfo.pw_name, userinfo.pw_uid, u_groups)
@ -406,7 +439,8 @@ if __name__ == "__main__":
# do we have root privileges (effective uid is zero)? # do we have root privileges (effective uid is zero)?
if os.geteuid() != 0: if os.geteuid() != 0:
sys.stderr.write("the effective uid is not zero - you should use 'super' to call this script (%s)" % sys.argv[0]) sys.stderr.write("the effective uid is not zero - you should use " \
+ "'super' to call this script (%s)" % sys.argv[0])
sys.exit(100) sys.exit(100)
# remove program name # remove program name
@ -468,7 +502,8 @@ if __name__ == "__main__":
elif progRequest == "mount": runner = run_mount elif progRequest == "mount": runner = run_mount
elif progRequest == "umount": runner = run_umount elif progRequest == "umount": runner = run_umount
else: else:
sys.stderr.write("The interface for this program (%s) is not yet implemented!\n" % progRequest) sys.stderr.write("The interface for this program (%s) is " \
+ "not yet implemented!\n" % progRequest)
sys.exit(100) sys.exit(100)
try: try:
if runner(args): if runner(args):

View File

@ -10,7 +10,8 @@
<?cs include:Settings.TemplateFile ?> <?cs include:Settings.TemplateFile ?>
<?cs include:Settings.TemplateDir + '/show_volume_footer.cs' ?> <?cs include:Settings.TemplateDir + '/show_volume_footer.cs' ?>
<?cs else ?> <?cs else ?>
<?cs # remove or enable??? call:show_system_plugin_overview() ?> <?cs # enable only, if "system_preferences" is colored, too
call:show_system_plugin_overview() ?>
<?cs include:Settings.TemplateFile ?> <?cs include:Settings.TemplateFile ?>
<?cs /if ?> <?cs /if ?>

View File

@ -23,6 +23,7 @@
body { body {
text-align: center; text-align: center;
font-size: 0.9em;
margin: 0; margin: 0;
padding: 0; padding: 0;
font-family: verdana, lucida, arial, helvetica, sans-serif; font-family: verdana, lucida, arial, helvetica, sans-serif;