diff --git a/bin/cryptobox.conf b/bin/cryptobox.conf index 31c80c8..839995e 100644 --- a/bin/cryptobox.conf +++ b/bin/cryptobox.conf @@ -3,6 +3,7 @@ # comma separated list of possible prefixes for accesible devices # beware: .e.g "/dev/hd" grants access to _all_ harddisks AllowedDevices = /dev/loop, /dev/ubdb, /dev/md_d127 +#AllowedDevices = /dev/ # use separate config partition? (1=yes / 0=no) UseConfigPartition = 1 @@ -86,7 +87,7 @@ nice = /usr/bin/nice super = /usr/bin/super # this is the "program" name as defined in /etc/super.tab # "CryptoBoxRootActionsLocal" (in /etc/super.tab) should point to the -# CryptoBoxRootActions.py file in your local sorkign directory - this avoids +# CryptoBoxRootActions.py file in your local working directory - this avoids # conflicts with a locally (apt-)installed CryptoBoxRootActions.py file CryptoBoxRootActions = CryptoBoxRootActionsLocal diff --git a/src/cryptobox/core/blockdevice.py b/src/cryptobox/core/blockdevice.py index 69e55ad..3c8df41 100644 --- a/src/cryptobox/core/blockdevice.py +++ b/src/cryptobox/core/blockdevice.py @@ -467,17 +467,17 @@ class Blockdevice: stderr = subprocess.PIPE, args = [ prefs["Programs"]["cryptsetup"], "luksUUID", self.devnodes[0] ]) - proc.wait() + (output, error) = proc.communicate() except OSError, err_msg: LOGGER.warning("Failed to call '%s' to determine UUID: %s" \ % (prefs["Programs"]["cryptsetup"], err_msg)) return None if proc.returncode != 0: - LOGGER.warning("Execution of '%s' failed: %s" % \ - (prefs["Programs"]["cryptsetup"], - proc.stderr.read().strip())) + LOGGER.warning("Execution of '%s' for '%s' failed: %s" % \ + (prefs["Programs"]["cryptsetup"], self.devnodes[0], + error)) return None - result = proc.stdout.read().strip() + result = output.strip() if result: return result else: @@ -496,16 +496,15 @@ class Blockdevice: args = [ prefs["Programs"]["super"], prefs["Programs"]["CryptoBoxRootActions"], "program", "pvdisplay" ]) - proc.wait() + (output, error) = proc.communicate() except OSError, err_msg: LOGGER.warning("Failed to call '%s' via 'super' to determine " \ % prefs["Programs"]["pvdisplay"] + "UUID: %s" % err_msg) return None if proc.returncode != 0: - LOGGER.warning("Execution of 'pvdisplay' failed: %s" % \ - proc.stderr.read().strip()) + LOGGER.warning("Execution of 'pvdisplay' failed: %s" % error) return None - for line in proc.stdout.readlines(): + for line in output.splitlines(): items = line.strip().split(":") if (len(items) == 12) and (items[0] in self.devnodes): return items[11] @@ -530,16 +529,17 @@ class Blockdevice: "-c", os.devnull, "-w", os.devnull, self.devnodes[0] ]) - proc.wait() + (output, error) = proc.communicate() except OSError, err_msg: LOGGER.warning("Failed to call '%s' to determine UUID: %s" % \ (prefs["Programs"]["blkid"], err_msg)) return None if proc.returncode != 0: - LOGGER.warning("Execution of '%s' failed: %s" % \ - (prefs["Programs"]["blkid"], proc.stderr.read().strip())) + LOGGER.warning("Execution of '%s' for '%s' failed: %s" % \ + (prefs["Programs"]["blkid"], self.devnodes[0], + error.strip())) return None - result = proc.stdout.read().strip() + result = output.strip() if result: return result else: @@ -549,10 +549,12 @@ class Blockdevice: def __get_label(self): """determine the label of a filesystem contained in a device - return None for errors, empty labels and for non-storage devices + return None for errors, empty labels and for luks or non-storage devices """ if not self.is_valid(): return None + if self.is_luks(): + return None prefs = _load_preferences() try: proc = subprocess.Popen( @@ -565,22 +567,29 @@ class Blockdevice: "-c", os.devnull, "-w", os.devnull, self.devnodes[0]]) - proc.wait() + (output, error) = proc.communicate() except OSError, err_msg: LOGGER.warning("Failed to call '%s' to determine label: %s" % \ (prefs["Programs"]["blkid"], err_msg)) return None if proc.returncode != 0: - LOGGER.warning("Execution of '%s' failed: %s" % \ - (prefs["Programs"]["blkid"], proc.stderr.read().strip())) + LOGGER.warning("Execution of '%s' for '%s' failed: %s" % \ + (prefs["Programs"]["blkid"], self.devnodes[0], + error.strip())) return None - result = proc.stdout.read().strip() + result = output.strip() if result: return result else: return None + def __eq__(self, device): + """compare two blockdevice objects + """ + return self.name == device.name + + def __str__(self): """display the name of the device """ @@ -764,17 +773,16 @@ def find_lvm_pv(): args = [ prefs["Programs"]["super"], prefs["Programs"]["CryptoBoxRootActions"], "program", "pvdisplay" ]) - proc.wait() + (output, error) = proc.communicate() except OSError, err_msg: LOGGER.info("Failed to call 'pvdisplay' via 'super': %s" % err_msg) result = [] if proc.returncode != 0: - LOGGER.info("Execution of 'pvdisplay' failed: %s" % \ - proc.stderr.read().strip()) + LOGGER.info("Execution of 'pvdisplay' failed: %s" % error.strip()) result = [] if result is None: result = [] - for line in proc.stdout.readlines(): + for line in output.splitlines(): result.append(line.split(":", 1)[0].strip()) CACHE.set(cache_link, result) return result[:] diff --git a/src/cryptobox/core/container.py b/src/cryptobox/core/container.py index 374cb3f..1d60199 100644 --- a/src/cryptobox/core/container.py +++ b/src/cryptobox/core/container.py @@ -281,7 +281,7 @@ class CryptoBoxContainer: self.cbox.prefs["Programs"]["CryptoBoxRootActions"], "program", "cryptsetup", "luksAddKey", - self.device.devnodes[0], + self.get_device(), "--batch-mode"]) proc.stdin.write("%s\n%s" % (oldpw, newpw)) (output, errout) = proc.communicate() @@ -306,7 +306,7 @@ class CryptoBoxContainer: self.cbox.prefs["Programs"]["cryptsetup"], "--batch-mode", "luksDelKey", - self.device.devnodes[0], + self.get_device(), "%d" % (keyslot, )]) proc.wait() if proc.returncode != 0: @@ -397,7 +397,7 @@ class CryptoBoxContainer: "-o", "value", "-c", os.devnull, "-w", os.devnull, - self.device.devnodes[0] ]) + self.get_device() ]) (stdout, stderr) = proc.communicate() if proc.returncode == 0: ## we found a uuid @@ -422,7 +422,7 @@ class CryptoBoxContainer: if not self.is_mounted(): return "unavailable" else: - container = self.device.devnodes[0] + container = self.get_device() proc = subprocess.Popen( shell = False, stdout = subprocess.PIPE, @@ -435,8 +435,8 @@ class CryptoBoxContainer: return stdout.split("TYPE=")[1] else: ## if something goes wrong don't dig deeper - self.cbox.log.warn("filesystem determination failed: %s" % \ - (stderr.strip(), )) + self.cbox.log.warn("Filesystem determination (%s) failed: %s" % \ + (self.get_device(), stderr.strip())) return "undetermined" return @@ -471,7 +471,7 @@ class CryptoBoxContainer: self.cbox.prefs["Programs"]["CryptoBoxRootActions"], "program", "cryptsetup", "luksOpen", - self.device.devnodes[0], + self.get_device(), self.name, "--batch-mode"]) proc.stdin.write(password) @@ -567,7 +567,7 @@ class CryptoBoxContainer: self.cbox.prefs["Programs"]["super"], self.cbox.prefs["Programs"]["CryptoBoxRootActions"], "program", "mount", - self.device.devnodes[0], + self.get_device(), self.__get_mount_point()]) proc.wait() if proc.returncode != 0: @@ -637,7 +637,7 @@ class CryptoBoxContainer: args = [ self.cbox.prefs["Programs"]["nice"], self.cbox.prefs["Programs"]["mkfs"], - "-t", fs_type, self.device.devnodes[0]]) + "-t", fs_type, self.get_device()]) loc_data.proc.wait() ## wait to allow error detection if loc_data.proc.returncode == 0: @@ -657,8 +657,8 @@ class CryptoBoxContainer: time.sleep(3) ## if the thread exited very fast, then it failed if not bg_task.isAlive(): - raise CBCreateError("formatting of device (%s) failed out " % self.device.devnodes[0] \ - + "of unknown reasons") + raise CBCreateError("formatting of device (%s) failed out " % \ + self.get_device() + "of unknown reasons") def __create_luks(self, password, fs_type="ext3"): @@ -682,7 +682,7 @@ class CryptoBoxContainer: self.cbox.prefs["Programs"]["CryptoBoxRootActions"], "program", "cryptsetup", "luksFormat", - self.device.devnodes[0], + self.get_device(), "--batch-mode", "--cipher", self.cbox.prefs["Main"]["DefaultCipher"], "--iter-time", "2000"]) @@ -703,7 +703,7 @@ class CryptoBoxContainer: self.cbox.prefs["Programs"]["CryptoBoxRootActions"], "program", "cryptsetup", "luksOpen", - self.device.devnodes[0], + self.get_device(), self.name, "--batch-mode"]) proc.stdin.write(password) @@ -754,8 +754,8 @@ class CryptoBoxContainer: time.sleep(3) ## if the thread exited very fast, then it failed if not bg_task.isAlive(): - raise CBCreateError("formatting of device (%s) failed out " % self.device.devnodes[0] \ - + "of unknown reasons") + raise CBCreateError("formatting of device (%s) failed out " \ + % self.get_device() + "of unknown reasons") def __clean_mount_dirs(self): diff --git a/src/cryptobox/core/main.py b/src/cryptobox/core/main.py index 8ccef58..7972801 100644 --- a/src/cryptobox/core/main.py +++ b/src/cryptobox/core/main.py @@ -249,8 +249,15 @@ class CryptoBox: def get_container(self, device): - "retrieve the container element for this device" - all = [e for e in self.get_container_list() if e.device.name == device.name] + """retrieve the container element for a device + + "device" can be a name (e.g. "dm-0") or a blockdevice object + """ + if isinstance(device, str): + devicename = device + else: + devicename = device.name + all = [e for e in self.get_container_list() if e.device.name == devicename] if all: return all[0] else: diff --git a/src/cryptobox/web/dataset.py b/src/cryptobox/web/dataset.py index a9ea029..974a284 100644 --- a/src/cryptobox/web/dataset.py +++ b/src/cryptobox/web/dataset.py @@ -25,7 +25,6 @@ __revision__ = "$Id$" import os import cryptobox.core.container as cbxContainer -import cryptobox.core.tools as cbxTools class WebInterfaceDataset(dict): @@ -34,6 +33,8 @@ class WebInterfaceDataset(dict): """ def __init__(self, cbox, prefs, plugin_manager): + """initialize the hdf dataset for the web site + """ super(WebInterfaceDataset, self).__init__() self.prefs = prefs self.cbox = cbox @@ -128,22 +129,21 @@ class WebInterfaceDataset(dict): """Set some hdf values according to the currently active disk. """ for container in self.cbox.get_container_list(): - if container.get_device() == device: + if container.device == device: is_encrypted = (container.get_type() == \ cbxContainer.CONTAINERTYPES["luks"]) and 1 or 0 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.device"] = device.name self["Data.CurrentDisk.name"] = container.get_name() self["Data.CurrentDisk.fs_type"] = container.get_fs_type() 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()) + self["Data.CurrentDisk.size"] = device.size_human if is_mounted: self.cbox.log.debug("Retrieving container's data: %s" % \ container.get_name()) @@ -158,8 +158,9 @@ class WebInterfaceDataset(dict): for key in self.keys(): if key.startswith("Data.CurrentDisk.capacity."): del self[key] - self["Settings.LinkAttrs.device"] = device - + break + self["Settings.LinkAttrs.device"] = device.name + def set_containers_state(self): """Set some hdf values according to the list of available containers. @@ -180,19 +181,20 @@ class WebInterfaceDataset(dict): 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.device" % avail_counter] = \ + container.device.name 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()) + container.device.size_human if is_mounted: active_counter += 1 avail_counter += 1 self["Data.activeDisksCount"] = active_counter - + def set_plugin_data(self): """Set some hdf values according to the available features. diff --git a/src/cryptobox/web/sites.py b/src/cryptobox/web/sites.py index 5b5ec60..2c2f00d 100644 --- a/src/cryptobox/web/sites.py +++ b/src/cryptobox/web/sites.py @@ -69,7 +69,7 @@ class PluginDownloadHandler: if not plugin: continue plname = plugin.get_name() - ## expose the get_icon function of this plugin + ## expose the download function of this plugin setattr(self, plname, plugin.download) @@ -324,7 +324,7 @@ class WebInterfaceSites: ## it will get ignored for non-volume plugins plugin.device = None if device and self.__set_device(device): - plugin.device = device + plugin.device = self.cbox.get_container(device).device ## check the device argument of volume plugins if "volume" in plugin.plugin_capabilities: ## initialize the dataset of the selected device if necessary @@ -340,7 +340,7 @@ class WebInterfaceSites: if redirect: override_next_template = { "plugin": redirect } if "volume" in plugin.plugin_capabilities: - override_next_template["values"] = {"device":plugin.device} + override_next_template["values"] = {"device":plugin.device.name} ## check for information to be kept after the last call if message_keep: for (key, value) in message_keep["dataset"].items(): @@ -357,7 +357,7 @@ class WebInterfaceSites: self.__dataset.set_current_disk_state(plugin.device) if not next_template: next_template = { "plugin":"volume_mount", - "values":{"device":plugin.device}} + "values":{"device":plugin.device.name}} else: ## some non-volume plugins change the internal state of other ## plugins - e.g.: plugin_manager @@ -370,7 +370,7 @@ class WebInterfaceSites: next_template = { "plugin":"disks", "values":{} } #TODO: there is a lot of piece-by-piece updating around here # for v0.4 we should just call __reset_dataset - but this would - # require to store the currently changed dataset values (e.g.i + # require to store the currently changed dataset values (e.g. # weblang) somewhere else to not override it ## some non-volume plugins may change the state of containers ## the mount plugin may change the number of active disks - for the logo @@ -524,7 +524,7 @@ class WebInterfaceSites: def __set_device(self, device): """check a device name that was chosen via the web interface issue a warning if the device is invalid""" - if device and re.match(r'[\w /\-]+$', device) \ + if device and re.match(r'[\w-]+$', device) \ and self.cbox.get_container(device): self.cbox.log.debug("Select device: %s" % device) return True