write nameDB immediately after change

add support for external hook scripts
This commit is contained in:
lars 2006-11-09 12:00:52 +00:00
parent c353c36772
commit 974a49ccc0
6 changed files with 96 additions and 24 deletions

View file

@ -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__":

View file

@ -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,32 +473,37 @@ 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():
proc = subprocess.Popen(
shell = False,
stdin = None,
stdout = devnull,
stderr = subprocess.PIPE,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"umount",
self.__getMountPoint()])
proc.wait()
if proc.returncode != 0:
errorMsg = "Could not umount the filesystem: %s" % (proc.stderr.read().strip(), )
self.log.warn(errorMsg)
raise CBUmountError(errorMsg)
self.cbox.sendEventNotification("preumount", self.__getEventArgs())
proc = subprocess.Popen(
shell = False,
stdin = None,
stdout = devnull,
stderr = subprocess.PIPE,
args = [
self.cbox.prefs["Programs"]["super"],
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
"umount",
self.__getMountPoint()])
proc.wait()
if proc.returncode != 0:
errorMsg = "Could not umount the filesystem: %s" % (proc.stderr.read().strip(), )
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()]

View file

@ -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))

View file

@ -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")

View file

@ -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]

View file

@ -51,6 +51,7 @@ TemplateDir = ../templates
LangDir = ../lang
DocDir = ../doc/html
PluginDir = ../plugins
HookDir = ../hook-scripts
[Log]
Level = debug
Destination = file