write nameDB immediately after change
add support for external hook scripts
This commit is contained in:
parent
c353c36772
commit
974a49ccc0
6 changed files with 96 additions and 24 deletions
|
@ -252,6 +252,7 @@ class CryptoBoxProps(CryptoBox):
|
|||
def removeUUID(self, uuid):
|
||||
if uuid in self.prefs.nameDB.keys():
|
||||
del self.prefs.nameDB[uuid]
|
||||
self.prefs.nameDB.write()
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
@ -269,6 +270,26 @@ class CryptoBoxProps(CryptoBox):
|
|||
return languages
|
||||
|
||||
|
||||
def sendEventNotification(self, event, event_infos):
|
||||
"""call all available scripts in the hook directory with some event information"""
|
||||
hook_dir = self.prefs["Locations"]["HookDir"]
|
||||
for fname in os.listdir(hook_dir):
|
||||
real_fname = os.path.join(hook_dir, fname)
|
||||
if os.path.isfile(real_fname) and os.access(real_fname, os.X_OK):
|
||||
cmd_args = [ self.prefs["Programs"]["super"],
|
||||
self.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"hook", real_fname, event]
|
||||
cmd_args.extend(event_infos)
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE,
|
||||
args = cmd_args)
|
||||
(stdout, stderr) = proc.communicate()
|
||||
if proc.returncode != 0:
|
||||
self.log.warn("a hook script (%s) failed (exitcode=%d) to handle an event (%s): %s" % (real_fname, proc.returncode, event, stderr.strip()))
|
||||
else:
|
||||
self.log.info("event handler (%s) finished successfully: %s" % (real_fname, event))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -354,6 +354,7 @@ class CryptoBoxContainer:
|
|||
errorMsg = "Could not create mountpoint (%s)" % (self.__getMountPoint(), )
|
||||
self.log.error(errorMsg)
|
||||
raise CBMountError(errorMsg)
|
||||
self.cbox.sendEventNotification("premount", self.__getEventArgs())
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdin = subprocess.PIPE,
|
||||
|
@ -390,6 +391,7 @@ class CryptoBoxContainer:
|
|||
self.log.warn(errorMsg)
|
||||
raise CBMountError(errorMsg)
|
||||
devnull.close()
|
||||
self.cbox.sendEventNotification("postmount", self.__getEventArgs())
|
||||
|
||||
|
||||
def __umountLuks(self):
|
||||
|
@ -399,6 +401,7 @@ class CryptoBoxContainer:
|
|||
devnull = open(os.devnull, "w")
|
||||
except IOError:
|
||||
self.log.warn("Could not open %s" % (os.devnull, ))
|
||||
self.cbox.sendEventNotification("preumount", self.__getEventArgs())
|
||||
if self.isMounted():
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
|
@ -434,6 +437,7 @@ class CryptoBoxContainer:
|
|||
self.log.warn(errorMsg)
|
||||
raise CBUmountError(errorMsg)
|
||||
devnull.close()
|
||||
self.cbox.sendEventNotification("postumount", self.__getEventArgs())
|
||||
|
||||
|
||||
def __mountPlain(self):
|
||||
|
@ -451,6 +455,7 @@ class CryptoBoxContainer:
|
|||
errorMsg = "Could not create mountpoint (%s)" % (self.__getMountPoint(), )
|
||||
self.log.error(errorMsg)
|
||||
raise CBMountError(errorMsg)
|
||||
self.cbox.sendEventNotification("premount", self.__getEventArgs())
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdin = None,
|
||||
|
@ -468,16 +473,20 @@ class CryptoBoxContainer:
|
|||
self.log.warn(errorMsg)
|
||||
raise CBMountError(errorMsg)
|
||||
devnull.close()
|
||||
self.cbox.sendEventNotification("postmount", self.__getEventArgs())
|
||||
|
||||
|
||||
def __umountPlain(self):
|
||||
"umount a plaintext partition"
|
||||
if not self.isMounted():
|
||||
self.cbox.log.info("trying to umount while volume (%s) is mounted" % self.getDevice())
|
||||
return
|
||||
devnull = None
|
||||
try:
|
||||
devnull = open(os.devnull, "w")
|
||||
except IOError:
|
||||
self.log.warn("Could not open %s" % (os.devnull, ))
|
||||
if self.isMounted():
|
||||
self.cbox.sendEventNotification("preumount", self.__getEventArgs())
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdin = None,
|
||||
|
@ -494,6 +503,7 @@ class CryptoBoxContainer:
|
|||
self.log.warn(errorMsg)
|
||||
raise CBUmountError(errorMsg)
|
||||
devnull.close()
|
||||
self.cbox.sendEventNotification("postumount", self.__getEventArgs())
|
||||
|
||||
|
||||
def __createPlain(self):
|
||||
|
@ -605,3 +615,9 @@ class CryptoBoxContainer:
|
|||
os.rmdir(abs_dir)
|
||||
|
||||
|
||||
def __getEventArgs(self):
|
||||
"""return an array of arguments for hook scripts handling pre/post-mount/umount
|
||||
events"""
|
||||
typeText = [e for e in self.Types.keys() if self.Types[e] == self.getType()][0]
|
||||
return [self.getDevice(), self.getName(), typeText, self.__getMountPoint()]
|
||||
|
||||
|
|
|
@ -30,11 +30,11 @@ allowedProgs = {
|
|||
DEV_TYPES = { "pipe":1, "char":2, "dir":4, "block":6, "file":8, "link":10, "socket":12}
|
||||
|
||||
|
||||
def checkIfPluginIsSafe(plugin):
|
||||
"""check if the plugin and its parents are only writeable for root"""
|
||||
def checkIfFileIsSafe(fname):
|
||||
"""check if the file and its parents are only writeable for root"""
|
||||
#FIXME: for now we may skip this test - but users will not like it this way :)
|
||||
return True
|
||||
props = os.stat(plugin)
|
||||
props = os.stat(fname)
|
||||
## check if it is owned by non-root
|
||||
if props.st_uid != 0: return False
|
||||
## check group-write permission if gid is not zero
|
||||
|
@ -42,9 +42,9 @@ def checkIfPluginIsSafe(plugin):
|
|||
## check if it is world-writeable
|
||||
if props.st_mode % 4 / 2 > 0: return False
|
||||
## are we at root-level (directory-wise)? If yes, then we are ok ...
|
||||
if plugin == os.path.sep: return True
|
||||
if fname == os.path.sep: return True
|
||||
## check if the parent directory is ok - recursively :)
|
||||
return checkIfPluginIsSafe(os.path.dirname(os.path.abspath(plugin)))
|
||||
return checkIfFileIsSafe(os.path.dirname(os.path.abspath(fname)))
|
||||
|
||||
|
||||
def checkIfPluginIsValid(plugin):
|
||||
|
@ -66,12 +66,12 @@ def call_plugin(args):
|
|||
"""check if the plugin may be called - and do it finally ..."""
|
||||
plugin = os.path.abspath(args[0])
|
||||
del args[0]
|
||||
## check existence and excutability
|
||||
## check existence and if it is executable
|
||||
if not os.access(plugin, os.X_OK):
|
||||
raise Exception, "could not find executable plugin (%s)" % plugin
|
||||
## check if the plugin (and its parents) are only writeable for root
|
||||
if not checkIfPluginIsSafe(plugin):
|
||||
raise Exception, "the plugin (%s) was not safe - check its (and its parents') permissions" % plugin
|
||||
if not checkIfFileIsSafe(plugin):
|
||||
raise Exception, "the plugin (%s) is not safe - check its (and its parents') permissions" % plugin
|
||||
## check if the plugin is a python program, that is marked as a cryptobox plugin
|
||||
if not checkIfPluginIsValid(plugin):
|
||||
raise Exception, "the plugin (%s) is not a correctly marked python script" % plugin
|
||||
|
@ -83,6 +83,24 @@ def call_plugin(args):
|
|||
return proc.returncode == 0
|
||||
|
||||
|
||||
def call_hook(args):
|
||||
"""check if the hook script may be called - and do it finally ..."""
|
||||
hook = os.path.abspath(args[0])
|
||||
del args[0]
|
||||
## check existence and if it is executable
|
||||
if not os.access(hook, os.X_OK):
|
||||
raise Exception, "could not find executable hook script (%s)" % hook
|
||||
## check if the hook (and its parents) are only writeable for root
|
||||
if not checkIfFileIsSafe(hook):
|
||||
raise Exception, "the hook (%s) is not safe - check its (and its parents') permissions" % hook
|
||||
args.insert(0,hook)
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
args = args)
|
||||
proc.wait()
|
||||
return proc.returncode == 0
|
||||
|
||||
|
||||
def isWriteable(device, force_dev_type=None):
|
||||
"""check if the calling user (not root!) has write access to the device/file
|
||||
|
||||
|
@ -356,6 +374,18 @@ if __name__ == "__main__":
|
|||
else:
|
||||
sys.exit(1)
|
||||
|
||||
if args[0].lower() == "hook":
|
||||
del args[0]
|
||||
try:
|
||||
isOK = call_hook(args)
|
||||
except Exception, errMsg:
|
||||
sys.stderr.write("Execution of hook script failed: %s\n" % errMsg)
|
||||
sys.exit(100)
|
||||
if isOK:
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
# check parameters count
|
||||
if len(args) < 2:
|
||||
sys.stderr.write("Not enough arguments supplied (%s)!\n" % " ".join(args))
|
||||
|
|
|
@ -363,6 +363,7 @@ TemplateDir = directoryExists(default="/usr/share/cryptobox/template")
|
|||
LangDir = directoryExists(default="/usr/share/cryptobox/lang")
|
||||
DocDir = directoryExists(default="/usr/share/doc/cryptobox/html")
|
||||
PluginDir = directoryExists(default="/usr/share/cryptobox/plugins")
|
||||
HookDir = directoryExists(default="/etc/cryptobox/hooks")
|
||||
|
||||
[Log]
|
||||
Level = option("debug", "info", "warn", "error", default="warn")
|
||||
|
|
|
@ -42,6 +42,9 @@ DocDir = ../doc/html
|
|||
#PluginDir = /usr/share/cryptobox/plugins
|
||||
PluginDir = ../plugins
|
||||
|
||||
# path to the hook directory (e.g. containing some scripts)
|
||||
#HookDir = /etc/cryptobox/hooks
|
||||
HookDir = ../hook-scripts
|
||||
|
||||
|
||||
[Log]
|
||||
|
|
|
@ -51,6 +51,7 @@ TemplateDir = ../templates
|
|||
LangDir = ../lang
|
||||
DocDir = ../doc/html
|
||||
PluginDir = ../plugins
|
||||
HookDir = ../hook-scripts
|
||||
[Log]
|
||||
Level = debug
|
||||
Destination = file
|
||||
|
|
Loading…
Reference in a new issue