fixed wrong redirection after reboot (causing reboot loop)
clarified interpretation of blkid output added missing success message to volume_format_fs execute formatting in the background mark busy devices as such fixed a small bug in CryptoBoxRootActions
|
@ -74,6 +74,7 @@ def checkIfPluginIsValid(plugin):
|
|||
import imp
|
||||
try:
|
||||
x = imp.load_source("cbox_plugin",plugin)
|
||||
#TODO: no wildcard catches, please!
|
||||
except Exception:
|
||||
return False
|
||||
try:
|
||||
|
@ -87,7 +88,7 @@ def checkIfPluginIsValid(plugin):
|
|||
|
||||
def checkIfEventScriptIsValid(plugin):
|
||||
event_dir = os.path.dirname(plugin)
|
||||
if os.path.exists(os.path.join(event_dir,EVENT_MARKER)):
|
||||
if os.path.exists(os.path.join(event_dir, EVENT_MARKER)):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
@ -106,7 +107,7 @@ def call_plugin(args):
|
|||
## 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
|
||||
args.insert(0,plugin)
|
||||
args.insert(0, plugin)
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
args = args)
|
||||
|
@ -122,12 +123,12 @@ def call_event(args):
|
|||
if not os.access(event, os.X_OK):
|
||||
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)
|
||||
if not checkIfEventScriptIsValid(plugin):
|
||||
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" % (plugin,EVENT_MARKER)
|
||||
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)
|
||||
## check if the event (and its parents) are only writeable for root
|
||||
if not checkIfFileIsSafe(event):
|
||||
raise Exception, "the event (%s) is not safe - check its (and its parents') permissions" % event
|
||||
args.insert(0,event)
|
||||
args.insert(0, event)
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
args = args)
|
||||
|
@ -201,7 +202,7 @@ def run_cryptsetup(args):
|
|||
cmd_args.append(action)
|
||||
cmd_args.append(device)
|
||||
elif action == "luksDelKey":
|
||||
if len(cs_args) < 2: raise "WrongArguments", "missing arguments"
|
||||
if len(args) < 2: raise "WrongArguments", "missing arguments"
|
||||
device = args[0]; del args[0]
|
||||
cmd_args.insert(-1, action)
|
||||
cmd_args.insert(-1, device)
|
||||
|
@ -361,7 +362,7 @@ def getUserInfo(user):
|
|||
except TypeError:
|
||||
# if a KeyError is raised again, then the supplied user was invalid
|
||||
userinfo = pwd.getpwnam(user)
|
||||
u_groups =[one_group.gr_gid
|
||||
u_groups = [one_group.gr_gid
|
||||
for one_group in grp.getgrall()
|
||||
if userinfo.pw_name in one_group.gr_mem]
|
||||
if not userinfo.pw_gid in u_groups: u_groups.append(userinfo.pw_gid)
|
||||
|
|
|
@ -76,11 +76,12 @@ Languages = en, de, sl, fr
|
|||
|
||||
[Programs]
|
||||
cryptsetup = /sbin/cryptsetup
|
||||
mkfs-data = /sbin/mkfs.ext3
|
||||
mkfs = /sbin/mkfs
|
||||
blkid = /sbin/blkid
|
||||
blockdev = /sbin/blockdev
|
||||
mount = /bin/mount
|
||||
umount = /bin/umount
|
||||
nice = /usr/bin/nice
|
||||
super = /usr/bin/super
|
||||
# this is the "program" name as defined in /etc/super.tab
|
||||
CryptoBoxRootActions = CryptoBoxRootActions
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
[global]
|
||||
server.socketPort = 8080
|
||||
#server.environment = "production"
|
||||
server.environment = "development"
|
||||
server.logToScreen = True
|
||||
server.log_tracebacks = True
|
||||
server.threadPool = 1
|
||||
server.reverseDNS = False
|
||||
server.logFile = "cryptoboxwebserver.log"
|
||||
|
||||
[/favicon.ico]
|
||||
static_filter.on = True
|
||||
# TODO: use live-cd/live-cd-tree.d/var/www/favicon.ico
|
||||
static_filter.file = "/usr/share/doc/python-cherrypy/cherrypy/favicon.ico"
|
||||
|
||||
[/test_stream]
|
||||
stream_response = True
|
|
@ -75,11 +75,12 @@ Languages = de, en, fr
|
|||
|
||||
[Programs]
|
||||
cryptsetup = /sbin/cryptsetup
|
||||
mkfs-data = /sbin/mkfs.ext3
|
||||
mkfs = /sbin/mkfs
|
||||
blkid = /sbin/blkid
|
||||
blockdev = /sbin/blockdev
|
||||
mount = /bin/mount
|
||||
umount = /bin/umount
|
||||
nice = /usr/bin/nice
|
||||
super = /usr/bin/super
|
||||
# this is the "program" name as defined in /etc/super.tab
|
||||
CryptoBoxRootActions = CryptoBoxRootActions
|
||||
|
|
7
debian/changelog
vendored
|
@ -1,3 +1,10 @@
|
|||
cryptobox (0.2.52-1) unstable; urgency=low
|
||||
|
||||
* format partitions in background
|
||||
* mark busy partitions
|
||||
|
||||
-- Lars Kruse <devel@sumpfralle.de> Wed, 6 Dec 2006 14:57:43 +0100
|
||||
|
||||
cryptobox (0.2.51-1) unstable; urgency=low
|
||||
|
||||
* favicon included
|
||||
|
|
|
@ -28,6 +28,7 @@ import os
|
|||
import logging
|
||||
import cryptobox.core.tools as cbxTools
|
||||
import cryptobox.plugins.base
|
||||
from cryptobox.core.exceptions import *
|
||||
|
||||
|
||||
PARTTYPES = {
|
||||
|
@ -228,7 +229,7 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
|||
## breaks the flow (hanging process)
|
||||
#self.cbox.reReadContainerList()
|
||||
## write config data
|
||||
self.cbox.prefs.mountPartition()
|
||||
self.cbox.prefs.mount_partition()
|
||||
self.cbox.prefs.write()
|
||||
self.cbox.log.info("settings stored on config partition")
|
||||
## return the result
|
||||
|
@ -456,6 +457,26 @@ class partition(cryptobox.plugins.base.CryptoBoxPlugin):
|
|||
|
||||
|
||||
def __format_one_partition(self, dev_name, fs_type):
|
||||
"""Format a single partition
|
||||
"""
|
||||
import cryptobox.core.container
|
||||
## first: retrieve UUID - it can be removed from the database afterwards
|
||||
prev_name = [e.get_name() for e in self.cbox.get_container_list()
|
||||
if e.get_device() == dev_name]
|
||||
## call "mkfs"
|
||||
try:
|
||||
cont = cryptobox.core.container.CryptoBoxContainer(dev_name, self.cbox)
|
||||
cont.create(cryptobox.core.container.CONTAINERTYPES["plain"], fs_type=fs_type)
|
||||
except (CBInvalidType, CBCreateError, CBVolumeIsActive), err_msg:
|
||||
self.cbox.log.warn(err_msg)
|
||||
return False
|
||||
## remove unused volume entry
|
||||
if prev_name:
|
||||
del self.cbox.prefs.volumes_db[prev_name[0]]
|
||||
return True
|
||||
|
||||
|
||||
def __old_format_one_partition(self, dev_name, fs_type):
|
||||
"""Format a single partition
|
||||
"""
|
||||
## first: retrieve UUID - it can be removed from the database afterwards
|
||||
|
|
|
@ -22,7 +22,7 @@ __revision__ = "$Id"
|
|||
|
||||
import cryptobox.plugins.base
|
||||
|
||||
REDIRECT_DELAY = 180
|
||||
REDIRECT_DELAY = 120
|
||||
|
||||
class shutdown(cryptobox.plugins.base.CryptoBoxPlugin):
|
||||
|
||||
|
@ -44,7 +44,7 @@ class shutdown(cryptobox.plugins.base.CryptoBoxPlugin):
|
|||
elif type == "reboot":
|
||||
if self.__do_shutdown("reboot"):
|
||||
self.hdf["Data.Success"] = "Plugins.shutdown.Reboot"
|
||||
self.hdf["Data.Redirect.URL"] = ""
|
||||
self.hdf["Data.Redirect.URL"] = "/"
|
||||
self.hdf["Data.Redirect.Delay"] = REDIRECT_DELAY
|
||||
return "progress_reboot"
|
||||
else:
|
||||
|
|
|
@ -31,8 +31,8 @@ AdviceMessage {
|
|||
|
||||
SuccessMessage {
|
||||
FormatSuccess {
|
||||
Title = Formatting successful
|
||||
Text = The selected filesystem was successfully formatted.
|
||||
Title = Formatting is running
|
||||
Text = The selected filesystem is being formatted in the background. This may take some time (depending on the size of your disk).
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ class volume_format_fs(cryptobox.plugins.base.CryptoBoxPlugin):
|
|||
|
||||
def do_action(self, store=None, fs_type="windows", container_type="luks", crypto_password=None, crypto_password2=None, confirm=None):
|
||||
if not fs_type in FSTYPES.keys():
|
||||
self.cbox.info
|
||||
self.cbox.log.info("invalid filesystem type choosen: %s" % str(fs_type))
|
||||
return "format_volume"
|
||||
self.hdf[self.hdf_prefix + "fs_type"] = fs_type
|
||||
self.hdf[self.hdf_prefix + "container_type"] = container_type
|
||||
|
@ -54,10 +54,10 @@ class volume_format_fs(cryptobox.plugins.base.CryptoBoxPlugin):
|
|||
if container_type == "luks":
|
||||
return "volume_format_luks"
|
||||
elif container_type == "plain":
|
||||
return self.__format_plain(fs_type)
|
||||
return self.__format_plain(FSTYPES[fs_type])
|
||||
elif store == "step2":
|
||||
if container_type == "luks":
|
||||
return self.__format_luks(fs_type, crypto_password, crypto_password2)
|
||||
return self.__format_luks(FSTYPES[fs_type], crypto_password, crypto_password2)
|
||||
else:
|
||||
self.cbox.log.info("invalid input value for 'container_type': %s" % container_type)
|
||||
return "volume_format"
|
||||
|
@ -72,36 +72,10 @@ class volume_format_fs(cryptobox.plugins.base.CryptoBoxPlugin):
|
|||
return "no status"
|
||||
|
||||
|
||||
def __format_plain(self, fsType):
|
||||
def __format_plain(self, fs_type):
|
||||
try:
|
||||
container = self.cbox.get_container(self.device)
|
||||
container.create(cbx_container.CONTAINERTYPES["plain"])
|
||||
except CBVolumeIsActive:
|
||||
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
|
||||
self.cbox.log.info("initialization is not possible as long as the device (%s) is mounted" % self.device)
|
||||
return None
|
||||
except CBContainerError, errMsg:
|
||||
self.hdf["Data.Warning"] = "Plugins.volume_format_fs.FormatFailed"
|
||||
self.cbox.log.warn("initialization of device '%s' failed" % self.device)
|
||||
self.cbox.log.warn("reason: %s" % errMsg)
|
||||
return "volume_format"
|
||||
else:
|
||||
self.cbox.log.info("successfully initialized device '%s'" % self.device)
|
||||
return None
|
||||
|
||||
|
||||
def __format_luks(self, fsType, pw, pw2):
|
||||
if not pw:
|
||||
self.hdf["Data.Warning"] = "EmptyPassword"
|
||||
self.cbox.log.warn("no crypto password was supplied for initialization of device '%s'" % self.device)
|
||||
return "volume_format"
|
||||
if pw != pw2:
|
||||
self.hdf["Data.Warning"] = "DifferentPasswords"
|
||||
self.cbox.log.warn("the crypto password was not repeated correctly for initialization of device '%s'" % self.device)
|
||||
return "volume_format"
|
||||
container = self.cbox.get_container(self.device)
|
||||
try:
|
||||
container.create(cbx_container.CONTAINERTYPES["luks"], pw)
|
||||
container.create(cbx_container.CONTAINERTYPES["plain"], fs_type=fs_type)
|
||||
except CBVolumeIsActive:
|
||||
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
|
||||
self.cbox.log.info("initialization is not possible as long as the device (%s) is mounted" % self.device)
|
||||
|
@ -114,5 +88,33 @@ class volume_format_fs(cryptobox.plugins.base.CryptoBoxPlugin):
|
|||
else:
|
||||
self.hdf["Data.Success"] = "Plugins.volume_format_fs.FormatSuccess"
|
||||
self.cbox.log.info("successfully initialized device '%s'" % self.device)
|
||||
return None
|
||||
return { "plugin":"disks", "values":{} }
|
||||
|
||||
|
||||
def __format_luks(self, fs_type, pw, pw2):
|
||||
if not pw:
|
||||
self.hdf["Data.Warning"] = "EmptyPassword"
|
||||
self.cbox.log.warn("no crypto password was supplied for initialization of device '%s'" % self.device)
|
||||
return "volume_format"
|
||||
if pw != pw2:
|
||||
self.hdf["Data.Warning"] = "DifferentPasswords"
|
||||
self.cbox.log.warn("the crypto password was not repeated correctly for initialization of device '%s'" % self.device)
|
||||
return "volume_format"
|
||||
container = self.cbox.get_container(self.device)
|
||||
try:
|
||||
container.create(cbx_container.CONTAINERTYPES["luks"],
|
||||
fs_type=fs_type, password=pw)
|
||||
except CBVolumeIsActive:
|
||||
self.hdf["Data.Warning"] = "VolumeMayNotBeMounted"
|
||||
self.cbox.log.info("initialization is not possible as long as the device (%s) is mounted" % self.device)
|
||||
return None
|
||||
except CBContainerError, errMsg:
|
||||
self.hdf["Data.Warning"] = "Plugins.volume_format_fs.FormatFailed"
|
||||
self.cbox.log.warn("initialization of device '%s' failed" % self.device)
|
||||
self.cbox.log.warn("reason: %s" % errMsg)
|
||||
return "volume_format"
|
||||
else:
|
||||
self.hdf["Data.Success"] = "Plugins.volume_format_fs.FormatSuccess"
|
||||
self.cbox.log.info("successfully initialized device '%s'" % self.device)
|
||||
return { "plugin":"disks", "values":{} }
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ __revision__ = "$Id"
|
|||
import subprocess
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
from cryptobox.core.exceptions import *
|
||||
|
||||
|
||||
|
@ -36,6 +37,10 @@ CONTAINERTYPES = {
|
|||
"swap":3,
|
||||
}
|
||||
|
||||
FSTYPES = {
|
||||
"plain":["ext3", "ext2", "vfat", "reiserfs"],
|
||||
"swap":["swap"]}
|
||||
|
||||
|
||||
## we use this marker to make sure, that we do not remove a non-cryptobox directory
|
||||
## below the mount directory
|
||||
|
@ -46,10 +51,6 @@ class CryptoBoxContainer:
|
|||
"""Manage a container of the CryptoBox
|
||||
"""
|
||||
|
||||
__fsTypes = {
|
||||
"plain":["ext3", "ext2", "vfat", "reiserfs"],
|
||||
"swap":["swap"]}
|
||||
|
||||
__dmDir = "/dev/mapper"
|
||||
|
||||
|
||||
|
@ -101,10 +102,10 @@ class CryptoBoxContainer:
|
|||
raise CBVolumeIsActive("the container must not be active during renaming")
|
||||
if not re.search(r'^[a-zA-Z0-9_\.\- ]+$', new_name):
|
||||
raise CBInvalidName("the supplied new name contains illegal characters")
|
||||
## check for another partitions with the same name
|
||||
## check for another partition with the same name
|
||||
if self.cbox.get_container_list(filter_name=new_name):
|
||||
raise CBNameIsInUse("the supplied new name is already in use for anonther partition")
|
||||
## maybe there a is an entry in the volumes database (but the partition is not active
|
||||
## maybe there a is an entry in the volumes database (but the partition is not active)
|
||||
try:
|
||||
## remove possibly existing inactive database item
|
||||
del self.cbox.prefs.volumes_db[new_name]
|
||||
|
@ -182,23 +183,64 @@ class CryptoBoxContainer:
|
|||
self.umount = self.__umount_plain
|
||||
|
||||
|
||||
def create(self, cont_type, password=None):
|
||||
def create(self, cont_type, password=None, fs_type="ext3"):
|
||||
"""Format a container.
|
||||
|
||||
Also set a password for encrypted container.
|
||||
"""
|
||||
if not fs_type in FSTYPES["plain"]:
|
||||
raise CBInvalidType("invalid filesystem type supplied: %s" % str(fs_type))
|
||||
old_name = self.get_name()
|
||||
if cont_type == CONTAINERTYPES["luks"]:
|
||||
self.__create_luks(password)
|
||||
self.__create_luks(password, fs_type)
|
||||
elif cont_type == CONTAINERTYPES["plain"]:
|
||||
self.__create_plain()
|
||||
self.__create_plain(fs_type)
|
||||
else:
|
||||
raise CBInvalidType("invalid container type (%d) supplied" % (cont_type, ))
|
||||
## no exception was raised during creation -> we can continue
|
||||
## reset the properties (encryption state, ...) of the device
|
||||
self.reset_object()
|
||||
## restore the old name (must be after reset_object)
|
||||
self.set_name(old_name)
|
||||
try:
|
||||
self.set_name(old_name)
|
||||
except CBNameIsInUse:
|
||||
## failure is okay
|
||||
pass
|
||||
|
||||
|
||||
def set_busy(self, new_state, time_limit=300):
|
||||
"""Set the current busy state.
|
||||
|
||||
The timelimit is specified in seconds.
|
||||
"""
|
||||
if new_state:
|
||||
self.cbox.busy_devices[self.device] = int(time.time() + time_limit)
|
||||
else:
|
||||
try:
|
||||
if self.cbox.busy_devices[self.device]:
|
||||
del self.cbox.busy_devices[self.device]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
def is_busy(self):
|
||||
"""Check the busy state of the container.
|
||||
"""
|
||||
if not self.cbox.busy_devices.has_key(self.device):
|
||||
self.cbox.log.debug("no 'busy' attribute for '%s'" % self.get_name())
|
||||
return False
|
||||
## invalid value - can happen after saving and loading the database
|
||||
if not isinstance(self.cbox.busy_devices[self.device], int):
|
||||
self.cbox.log.debug("invalid 'busy' attribute for '%s'" % self.get_name())
|
||||
del db_entry["busy"]
|
||||
return False
|
||||
if time.time() >= self.cbox.busy_devices[self.device]:
|
||||
self.cbox.log.debug("expired 'busy' attribute for '%s'" % self.get_name())
|
||||
del db_entry["busy"]
|
||||
return False
|
||||
## lock is still active
|
||||
self.cbox.log.debug("active 'busy' attribute for '%s'" % self.get_name())
|
||||
return True
|
||||
|
||||
|
||||
def change_password(self, oldpw, newpw):
|
||||
|
@ -362,9 +404,9 @@ class CryptoBoxContainer:
|
|||
if self.__is_luks_partition():
|
||||
return CONTAINERTYPES["luks"]
|
||||
type_of_partition = self.__get_type_id_of_partition()
|
||||
if type_of_partition in self.__fsTypes["plain"]:
|
||||
if type_of_partition in FSTYPES["plain"]:
|
||||
return CONTAINERTYPES["plain"]
|
||||
if type_of_partition in self.__fsTypes["swap"]:
|
||||
if type_of_partition in FSTYPES["swap"]:
|
||||
return CONTAINERTYPES["swap"]
|
||||
return CONTAINERTYPES["unused"]
|
||||
|
||||
|
@ -372,29 +414,28 @@ class CryptoBoxContainer:
|
|||
def __get_type_id_of_partition(self):
|
||||
"returns the type of the partition (see 'man blkid')"
|
||||
devnull = None
|
||||
try:
|
||||
devnull = open(os.devnull, "w")
|
||||
except IOError:
|
||||
self.cbox.log.warn("Could not open %s" % (os.devnull, ))
|
||||
proc = subprocess.Popen(
|
||||
shell=False,
|
||||
stdin=None,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
args=[self.cbox.prefs["Programs"]["blkid"],
|
||||
shell = False,
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE,
|
||||
args = [ self.cbox.prefs["Programs"]["blkid"],
|
||||
"-s", "TYPE",
|
||||
"-o", "value",
|
||||
"-c", os.devnull,
|
||||
"-w", os.devnull,
|
||||
self.device])
|
||||
proc.wait()
|
||||
output = proc.stdout.read().strip()
|
||||
if proc.returncode != 0:
|
||||
self.cbox.log.warn("retrieving of partition type via 'blkid' failed: %s" % \
|
||||
(proc.stderr.read().strip(), ))
|
||||
self.device ])
|
||||
(stdout, stder) = proc.communicate()
|
||||
if proc.returncode == 0:
|
||||
## we found a uuid
|
||||
return stdout.strip()
|
||||
elif proc.returncode == 2:
|
||||
## failed to find the attribute - no problem
|
||||
return None
|
||||
else:
|
||||
## something strange happened
|
||||
self.cbox.log.warn("retrieving of partition type via 'blkid' failed: %s" % \
|
||||
(stderr.strip(), ))
|
||||
return None
|
||||
devnull.close()
|
||||
return output
|
||||
|
||||
|
||||
def __is_luks_partition(self):
|
||||
|
@ -596,50 +637,63 @@ class CryptoBoxContainer:
|
|||
self.cbox.send_event_notification("postumount", self.__get_event_args())
|
||||
|
||||
|
||||
def __create_plain(self):
|
||||
def __create_plain(self, fs_type="ext3"):
|
||||
"make a plaintext partition"
|
||||
import threading
|
||||
if self.is_mounted():
|
||||
raise CBVolumeIsActive("deactivate the partition before filesystem initialization")
|
||||
devnull = None
|
||||
try:
|
||||
devnull = open(os.devnull, "w")
|
||||
except IOError:
|
||||
self.cbox.log.warn("Could not open %s" % (os.devnull, ))
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdin = None,
|
||||
stdout = devnull,
|
||||
stderr = subprocess.PIPE,
|
||||
args = [
|
||||
self.cbox.prefs["Programs"]["mkfs-data"],
|
||||
self.device])
|
||||
proc.wait()
|
||||
if proc.returncode != 0:
|
||||
err_msg = "Could not create the filesystem: %s" % (proc.stderr.read().strip(), )
|
||||
self.cbox.log.error(err_msg)
|
||||
raise CBCreateError(err_msg)
|
||||
devnull.close()
|
||||
raise CBVolumeIsActive(
|
||||
"deactivate the partition before filesystem initialization")
|
||||
def format():
|
||||
import os
|
||||
old_name = self.get_name()
|
||||
self.set_busy(True, 600)
|
||||
self.cbox.log.debug("Turn the busy flag on: %s" % self.device)
|
||||
## give the main thread a chance to continue
|
||||
child_pid = os.fork()
|
||||
if child_pid == 0:
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdin = None,
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE,
|
||||
args = [
|
||||
self.cbox.prefs["Programs"]["nice"],
|
||||
self.cbox.prefs["Programs"]["mkfs"],
|
||||
"-t", fs_type, self.device])
|
||||
(stdout, sterr) = proc.communicate()
|
||||
## for to allow error detection
|
||||
if proc.returncode == 0:
|
||||
time.sleep(5)
|
||||
## skip cleanup stuff (as common for sys.exit)
|
||||
os._exit(0)
|
||||
else:
|
||||
os.waitpid(child_pid, 0)
|
||||
self.set_name(old_name)
|
||||
self.set_busy(False)
|
||||
self.cbox.log.debug("Turn the busy flag off: %s" % self.device)
|
||||
bg_task = threading.Thread(target=format)
|
||||
bg_task.start()
|
||||
time.sleep(3)
|
||||
## if the thread exited very fast, then it failed
|
||||
if not bg_task.isAlive():
|
||||
raise CBCreateError("Failed to initilize device: %s" % self.device)
|
||||
|
||||
|
||||
def __create_luks(self, password):
|
||||
def __create_luks(self, password, fs_type="ext3"):
|
||||
"""Create a luks partition.
|
||||
"""
|
||||
import threading
|
||||
if not password:
|
||||
raise CBInvalidPassword("no password supplied for new luks mapping")
|
||||
if self.is_mounted():
|
||||
raise CBVolumeIsActive("deactivate the partition before filesystem initialization")
|
||||
devnull = None
|
||||
try:
|
||||
devnull = open(os.devnull, "w")
|
||||
except IOError:
|
||||
self.cbox.log.warn("Could not open %s" % (os.devnull, ))
|
||||
## remove any potential open luks mapping
|
||||
self.__umount_luks()
|
||||
## create the luks header
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdin = subprocess.PIPE,
|
||||
stdout = devnull,
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE,
|
||||
args = [
|
||||
self.cbox.prefs["Programs"]["super"],
|
||||
|
@ -660,7 +714,7 @@ class CryptoBoxContainer:
|
|||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdin = subprocess.PIPE,
|
||||
stdout = devnull,
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE,
|
||||
args = [
|
||||
self.cbox.prefs["Programs"]["super"],
|
||||
|
@ -676,24 +730,44 @@ class CryptoBoxContainer:
|
|||
err_msg = "Could not open the new luks mapping: %s" % (errout.strip(), )
|
||||
self.cbox.log.error(err_msg)
|
||||
raise CBCreateError(err_msg)
|
||||
## make the filesystem
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdin = None,
|
||||
stdout = devnull,
|
||||
stderr = subprocess.PIPE,
|
||||
args = [
|
||||
self.cbox.prefs["Programs"]["mkfs-data"],
|
||||
os.path.join(self.__dmDir, self.name)])
|
||||
proc.wait()
|
||||
## remove the mapping - for every exit status
|
||||
self.__umount_luks()
|
||||
if proc.returncode != 0:
|
||||
err_msg = "Could not create the filesystem: %s" % (proc.stderr.read().strip(), )
|
||||
self.cbox.log.error(err_msg)
|
||||
## remove the luks mapping
|
||||
raise CBCreateError(err_msg)
|
||||
devnull.close()
|
||||
def format_luks():
|
||||
import os
|
||||
old_name = self.get_name()
|
||||
self.set_busy(True, 600)
|
||||
self.cbox.log.debug("Turn the busy flag on: %s" % self.device)
|
||||
child_pid = os.fork()
|
||||
if child_pid == 0:
|
||||
## make the filesystem
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdin = None,
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE,
|
||||
args = [
|
||||
self.cbox.prefs["Programs"]["nice"],
|
||||
self.cbox.prefs["Programs"]["mkfs"],
|
||||
"-t", fs_type,
|
||||
os.path.join(self.__dmDir, self.name)])
|
||||
(stdou, stderr) = proc.communicate()
|
||||
## wait to allow error detection
|
||||
if proc.returncode == 0:
|
||||
time.sleep(5)
|
||||
## skip cleanup stuff (as common for sys.exit)
|
||||
os._exit(0)
|
||||
else:
|
||||
os.waitpid(child_pid, 0)
|
||||
self.set_name(old_name)
|
||||
self.set_busy(False)
|
||||
self.cbox.log.debug("Turn the busy flag off: %s" % self.device)
|
||||
## remove the mapping - for every exit status
|
||||
self.__umount_luks()
|
||||
bg_task = threading.Thread(target=format_luks)
|
||||
bg_task.setDaemon(True)
|
||||
bg_task.start()
|
||||
time.sleep(3)
|
||||
## if the thread exited very fast, then it failed
|
||||
if not bg_task.isAlive():
|
||||
raise CBCreateError("Failed to initilize device: %s" % self.device)
|
||||
|
||||
|
||||
def __clean_mount_dirs(self):
|
||||
|
|
|
@ -46,6 +46,7 @@ class CryptoBox:
|
|||
self.prefs = cbxSettings.CryptoBoxSettings(config_file)
|
||||
self.__run_tests()
|
||||
self.__containers = []
|
||||
self.busy_devices = {}
|
||||
self.reread_container_list()
|
||||
|
||||
|
||||
|
|
|
@ -455,7 +455,8 @@ Languages = list(min=1,default=list("en"))
|
|||
|
||||
[Programs]
|
||||
cryptsetup = fileExecutable(default="/sbin/cryptsetup")
|
||||
mkfs-data = fileExecutable(default="/sbin/mkfs.ext3")
|
||||
mkfs = fileExecutable(default="/sbin/mkfs")
|
||||
nice = fileExecutable(default="/usr/bin/nice")
|
||||
blkid = fileExecutable(default="/sbin/blkid")
|
||||
blockdev = fileExecutable(default="/sbin/blockdev")
|
||||
mount = fileExecutable(default="/bin/mount")
|
||||
|
|
|
@ -191,6 +191,14 @@ class CryptoBoxPlugin:
|
|||
return self.plugin_visibility
|
||||
|
||||
|
||||
def reset(self):
|
||||
"""Reinitialize the plugin.
|
||||
|
||||
This function should be called before every run
|
||||
"""
|
||||
self.hdf = {}
|
||||
|
||||
|
||||
def get_test_class(self):
|
||||
"""Return the unittest class of the feature.
|
||||
"""
|
||||
|
|
|
@ -103,11 +103,13 @@ class WebInterfaceDataset(dict):
|
|||
is_plain = (container.get_type() == \
|
||||
cbxContainer.CONTAINERTYPES["plain"]) and 1 or 0
|
||||
is_mounted = container.is_mounted() and 1 or 0
|
||||
is_busy = container.is_busy() and 1 or 0
|
||||
self["Data.CurrentDisk.device"] = container.get_device()
|
||||
self["Data.CurrentDisk.name"] = container.get_name()
|
||||
self["Data.CurrentDisk.encryption"] = is_encrypted
|
||||
self["Data.CurrentDisk.plaintext"] = is_plain
|
||||
self["Data.CurrentDisk.active"] = is_mounted
|
||||
self["Data.CurrentDisk.busy"] = is_busy
|
||||
self["Data.CurrentDisk.size"] = cbxTools.get_blockdevice_size_humanly(
|
||||
container.get_device())
|
||||
if is_mounted:
|
||||
|
@ -133,10 +135,12 @@ class WebInterfaceDataset(dict):
|
|||
is_plain = (container.get_type() == \
|
||||
cbxContainer.CONTAINERTYPES["plain"]) and 1 or 0
|
||||
is_mounted = container.is_mounted() and 1 or 0
|
||||
is_busy = container.is_busy() and 1 or 0
|
||||
self["Data.Disks.%d.device" % avail_counter] = container.get_device()
|
||||
self["Data.Disks.%d.name" % avail_counter] = container.get_name()
|
||||
self["Data.Disks.%d.encryption" % avail_counter] = is_encrypted
|
||||
self["Data.Disks.%d.plaintext" % avail_counter] = is_plain
|
||||
self["Data.Disks.%d.busy" % avail_counter] = is_busy
|
||||
self["Data.Disks.%d.active" % avail_counter] = is_mounted
|
||||
self["Data.Disks.%d.size" % avail_counter] = \
|
||||
cbxTools.get_blockdevice_size_humanly(container.get_device())
|
||||
|
|
|
@ -252,28 +252,20 @@ class WebInterfaceSites:
|
|||
""" returns a function that is suitable for handling a cherrypy
|
||||
page request
|
||||
"""
|
||||
def handler(self, **args):
|
||||
def handler(self, weblang="", device=None, redirect=None, message_keep=None, **args):
|
||||
"""this function handles a cherrypy page request
|
||||
"""
|
||||
plugin.reset()
|
||||
self.__reset_dataset()
|
||||
self.__check_environment()
|
||||
## set web interface language
|
||||
try:
|
||||
self.__set_web_lang(args["weblang"])
|
||||
del args["weblang"]
|
||||
except KeyError:
|
||||
self.__set_web_lang("")
|
||||
self.__set_web_lang(weblang)
|
||||
## we always read the "device" setting - otherwise volume-plugin
|
||||
## links would not work easily
|
||||
## (see "volume_props" linking to "volume_format_fs")
|
||||
## it will get ignored for non-volume plugins
|
||||
try:
|
||||
plugin.device = None
|
||||
if self.__set_device(args["device"]):
|
||||
plugin.device = args["device"]
|
||||
del args["device"]
|
||||
except KeyError:
|
||||
plugin.device = None
|
||||
plugin.device = None
|
||||
if device and self.__set_device(device):
|
||||
plugin.device = device
|
||||
## check the device argument of volume plugins
|
||||
if "volume" in plugin.plugin_capabilities:
|
||||
## initialize the dataset of the selected device if necessary
|
||||
|
@ -285,22 +277,18 @@ class WebInterfaceSites:
|
|||
## check if there is a "redirect" setting - this will override
|
||||
## the return value of the do_action function
|
||||
## (e.g. useful for umount-before-format)
|
||||
try:
|
||||
if args["redirect"]:
|
||||
override_next_template = { "plugin":args["redirect"] }
|
||||
if "volume" in plugin.plugin_capabilities:
|
||||
override_next_template["values"] = {"device":plugin.device}
|
||||
del args["redirect"]
|
||||
except KeyError:
|
||||
override_next_template = None
|
||||
override_next_template = None
|
||||
if redirect:
|
||||
override_next_template = { "plugin": redirect }
|
||||
if "volume" in plugin.plugin_capabilities:
|
||||
override_next_template["values"] = {"device":plugin.device}
|
||||
## check for information to be kept after the last call
|
||||
try:
|
||||
keep_values = args["message_keep"]
|
||||
del args["message_keep"]
|
||||
for key, value in keep_values["dataset"].items():
|
||||
if message_keep:
|
||||
for (key, value) in message_keep["dataset"].items():
|
||||
self.__dataset[key] = value
|
||||
except KeyError:
|
||||
keep_values = None
|
||||
## check if the device is busy
|
||||
if plugin.device and self.cbox.get_container(plugin.device).is_busy():
|
||||
return self.__render("volume_busy")
|
||||
## call the plugin handler
|
||||
next_template = plugin.do_action(**args)
|
||||
## for 'volume' plugins: reread the dataset of the current disk
|
||||
|
@ -330,7 +318,7 @@ class WebInterfaceSites:
|
|||
and self.__plugin_manager.get_plugin(next_template["plugin"]):
|
||||
value_dict = dict(next_template["values"])
|
||||
## force the current weblang attribute - otherwise it gets lost
|
||||
value_dict["weblang"] = self.__dataset["Settings.Language"]
|
||||
value_dict["weblang"] = self.lang_order[0]
|
||||
## check for warnings/success messages, that should be kept
|
||||
if "Data.Success" in plugin.hdf.keys() \
|
||||
or "Data.Warning" in plugin.hdf.keys():
|
||||
|
@ -354,7 +342,6 @@ class WebInterfaceSites:
|
|||
|
||||
|
||||
@cherrypy.expose
|
||||
@__request_auth
|
||||
def test(self, weblang=""):
|
||||
"""test authentication - this function may be safely removed
|
||||
"""
|
||||
|
@ -509,7 +496,10 @@ class WebInterfaceSites:
|
|||
if key == "LINK":
|
||||
return
|
||||
try:
|
||||
node.setValue("", translator.ugettext(node.value()))
|
||||
#TODO: we should use unicode - or not?
|
||||
#node.setValue("", translator.ugettext(node.value()))
|
||||
## quite obscure: ugettext can handle None - gettext breaks instead
|
||||
node.setValue("", str(translator.gettext(node.value())))
|
||||
except UnicodeEncodeError, err_msg:
|
||||
self.cbox.log.info(
|
||||
"Failed unicode encoding for gettext: %s - %s" \
|
||||
|
|
|
@ -22,6 +22,17 @@ Button {
|
|||
}
|
||||
|
||||
|
||||
AdviceMessage {
|
||||
|
||||
VolumeIsBusy {
|
||||
Title = Disk is busy
|
||||
Text = This disk is currently busy. Please wait for a moment.
|
||||
Link.Rel = /
|
||||
Link.Text = Show all disks
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WarningMessage {
|
||||
|
||||
AccessDenied {
|
||||
|
|
|
@ -119,15 +119,31 @@ def:show_volume_icon(volume) ?><?cs
|
|||
# show the appropriate icon for the current state of the volume ?><?cs
|
||||
if:volume.active ?><?cs
|
||||
if:volume.encryption ?><?cs
|
||||
set:filename='volume_active_crypto.gif' ?><?cs
|
||||
if:volume.busy ?><?cs
|
||||
set:filename='volume_active_crypto_busy.gif' ?><?cs
|
||||
else ?><?cs
|
||||
set:filename='volume_active_crypto.gif' ?><?cs
|
||||
/if ?><?cs
|
||||
else ?><?cs
|
||||
set:filename='volume_active_plain.gif' ?><?cs
|
||||
if:volume.busy ?><?cs
|
||||
set:filename='volume_active_plain_busy.gif' ?><?cs
|
||||
else ?><?cs
|
||||
set:filename='volume_active_plain.gif' ?><?cs
|
||||
/if ?><?cs
|
||||
/if ?><?cs
|
||||
else ?><?cs
|
||||
if:volume.encryption ?><?cs
|
||||
set:filename='volume_passive_crypto.gif' ?><?cs
|
||||
if:volume.busy ?><?cs
|
||||
set:filename='volume_passive_crypto_busy.gif' ?><?cs
|
||||
else ?><?cs
|
||||
set:filename='volume_passive_crypto.gif' ?><?cs
|
||||
/if ?><?cs
|
||||
else ?><?cs
|
||||
set:filename='volume_passive_plain.gif' ?><?cs
|
||||
if:volume.busy ?><?cs
|
||||
set:filename='volume_passive_plain_busy.gif' ?><?cs
|
||||
else ?><?cs
|
||||
set:filename='volume_passive_plain.gif' ?><?cs
|
||||
/if ?><?cs
|
||||
/if ?><?cs
|
||||
/if ?><img src="<?cs call:link('cryptobox-misc/' + filename,'','','','') ?>" alt="icon: volume" /><?cs
|
||||
/def ?><?cs
|
||||
|
|
8
templates/volume_busy.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?cs # $Id$ ?>
|
||||
|
||||
<?cs # display a warning because of a busy volume ?>
|
||||
|
||||
<?cs call:handle_messages() ?>
|
||||
|
||||
<?cs call:hint('VolumeIsBusy') ?>
|
||||
|
BIN
www-data/volume_active_crypto_busy.gif
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
www-data/volume_active_crypto_busy.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
www-data/volume_active_plain_busy.gif
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
www-data/volume_active_plain_busy.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
www-data/volume_passive_crypto_busy.gif
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
www-data/volume_passive_crypto_busy.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
www-data/volume_passive_plain_busy.gif
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
www-data/volume_passive_plain_busy.png
Normal file
After Width: | Height: | Size: 6.9 KiB |