reduce font size by one
improve user detection for CryptoBoxRootActions
This commit is contained in:
parent
871fce3f6d
commit
d8e0bbf429
|
@ -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):
|
||||||
|
|
|
@ -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 ?>
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue