changed the interface of CryptoBoxRootActions: "allowedProgs" are now prefixed with the parameter "program"
added allowedProg "pvdisplay" to CryptoBoxRootActions to allow LVM detection improved blockdevice handling: caching and detection of lvm, luks and raid
This commit is contained in:
parent
53e09ff825
commit
b72310097c
5 changed files with 470 additions and 85 deletions
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2006 sense.lab e.V.
|
||||
# Copyright 2007 sense.lab e.V.
|
||||
#
|
||||
# This file is part of the CryptoBox.
|
||||
#
|
||||
|
@ -20,13 +20,23 @@
|
|||
#
|
||||
|
||||
|
||||
"""module for executing the programs, that need root privileges
|
||||
"""module for executing some programs or scripts that need root privileges
|
||||
|
||||
Syntax:
|
||||
- TODO
|
||||
check
|
||||
- return exitcode zero if basic checks succeeded
|
||||
|
||||
this script will always return with an exitcode 0 (true),
|
||||
if "check" is the only argument
|
||||
program PROGRAM_NAME [ARGS]
|
||||
- call the program (must be defined in "allowedProgs" below)
|
||||
|
||||
event EVENT_SCRIPT [ARGS]
|
||||
- call an event script
|
||||
|
||||
plugin PLUGIN_NAME [ARGS]
|
||||
- call a root_action script of a plugin
|
||||
|
||||
For more detailed information take a look at the manpage:
|
||||
"man CryptoBoxRootActions"
|
||||
"""
|
||||
|
||||
__revision__ = "$Id"
|
||||
|
@ -44,6 +54,7 @@ allowedProgs = {
|
|||
"mount": "/bin/mount",
|
||||
"umount": "/bin/umount",
|
||||
"blkid": "/sbin/blkid",
|
||||
"pvdisplay": "/sbin/pvdisplay",
|
||||
}
|
||||
|
||||
## this line is necessary for running unittests or playing around with a local
|
||||
|
@ -387,6 +398,19 @@ def run_umount(args):
|
|||
return proc.returncode == 0
|
||||
|
||||
|
||||
def run_pvdisplay(args):
|
||||
"""execute pvdisplay to check for physical LVM devices
|
||||
"""
|
||||
if len(args) > 0:
|
||||
raise "WrongArguments", "no arguments may be supplied for 'pvdisplay'"
|
||||
## call pvdisplay with the parameter "--colon"
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
args = [ allowedProgs["pvdisplay"], "--colon" ])
|
||||
proc.wait()
|
||||
return proc.returncode == 0
|
||||
|
||||
|
||||
def getCallingUserInfo():
|
||||
"""return information about the user that was calling this program via "super"
|
||||
|
||||
|
@ -456,6 +480,7 @@ if __name__ == "__main__":
|
|||
# exit silently
|
||||
sys.exit(0)
|
||||
|
||||
## call a plugin root_action script
|
||||
if args[0].lower() == "plugin":
|
||||
del args[0]
|
||||
try:
|
||||
|
@ -468,6 +493,7 @@ if __name__ == "__main__":
|
|||
else:
|
||||
sys.exit(1)
|
||||
|
||||
## call an event script
|
||||
if args[0].lower() == "event":
|
||||
del args[0]
|
||||
try:
|
||||
|
@ -480,11 +506,13 @@ if __name__ == "__main__":
|
|||
else:
|
||||
sys.exit(1)
|
||||
|
||||
# check parameters count
|
||||
if len(args) < 2:
|
||||
sys.stderr.write("Not enough arguments supplied (%s)!\n" % " ".join(args))
|
||||
sys.exit(100)
|
||||
## call one of the allowed programs
|
||||
if args[0].lower() == "program":
|
||||
del args[0]
|
||||
|
||||
if len(args) < 1:
|
||||
sys.stderr.write("No program specified for execution\n")
|
||||
sys.exit(100)
|
||||
progRequest = args[0]
|
||||
del args[0]
|
||||
|
||||
|
@ -495,6 +523,7 @@ if __name__ == "__main__":
|
|||
if progRequest == "cryptsetup": runner = run_cryptsetup
|
||||
elif progRequest == "mount": runner = run_mount
|
||||
elif progRequest == "umount": runner = run_umount
|
||||
elif progRequest == "pvdisplay": runner = run_pvdisplay
|
||||
else:
|
||||
sys.stderr.write("The interface for this program (%s) is " \
|
||||
+ "not yet implemented!\n" % progRequest)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.TH CryptoBoxRootActions 8 "March 02007" "CryptoBox" "CryptoBox-Server manual"
|
||||
.TH CryptoBoxRootActions 8 "August 02007" "CryptoBox" "CryptoBox-Server manual"
|
||||
.SH NAME
|
||||
CryptoBoxRootActions \- The CryptoBoxWebserver calls this script in order to
|
||||
execute various programs which require root privileges.
|
||||
|
@ -13,7 +13,7 @@ plugin \fIFEATURE_SCRIPT\fR [\fIARGS\fR]
|
|||
hook \fIEVENT_SCRIPT\fR [\fIARGS\fR]
|
||||
.br
|
||||
.B CryptoBoxRootActions
|
||||
\fIPROG\fR [\fIARGS\fR]
|
||||
program \fIPROG\fR [\fIARGS\fR]
|
||||
.SH DESCRIPTION
|
||||
CryptoBoxRootActions is a script that is called by the
|
||||
\fBCryptoBox\fR-Server to execute programs which require root privileges. You
|
||||
|
@ -30,7 +30,8 @@ CryptoBoxRootActions /usr/sbin/CryptoBoxRootActions cryptobox
|
|||
.PP
|
||||
We assume that the CryptoBoxRootActions script is located at
|
||||
\fI/usr/sbin/CryptoBoxRootActions\fR. Furthermore the user running the
|
||||
CryptoBox-Server is assumed to be \fIcryptobox\fR.
|
||||
CryptoBox-Server is assumed to be \fIcryptobox\fR. Otherwise you must change the
|
||||
above line accordingly.
|
||||
.SH CONFIGURATION CHECK
|
||||
Call the CryptoBoxRootActions script with the argument \fIcheck\fR to test if
|
||||
\fBsuper\fR is configured properly. Just type the following:
|
||||
|
|
|
@ -25,26 +25,44 @@ These classes detect and filter available blockdevices.
|
|||
__revision__ = "$Id$"
|
||||
|
||||
|
||||
"""
|
||||
TODO:
|
||||
- implement some caching
|
||||
- find the devnodes for each device (e.g. /dev/hda)
|
||||
- detect luks devices
|
||||
- detect LVM
|
||||
"""
|
||||
|
||||
#TODO: use logger to report interesting behaviour
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
import cryptobox.core.settings
|
||||
|
||||
|
||||
DEFAULT_SYSBLOCK_DIR = '/sys/block'
|
||||
DEFAULT_DEVNODE_DIR = '/dev'
|
||||
MINIMUM_STORAGE_SIZE = 20
|
||||
MAJOR_DEVNUM_RAM = 1
|
||||
MAJOR_DEVNUM_LOOP = 7
|
||||
MAJOR_DEVNUM_MD_RAID = 9
|
||||
|
||||
USE_CACHE = True
|
||||
CACHE_EXPIRE_SECONDS = 60
|
||||
|
||||
#TODO: remove this after profiling
|
||||
IS_VISIBLE = True
|
||||
|
||||
## caching is quite important for the following implementation
|
||||
CACHED_VALUES = {}
|
||||
|
||||
class Blockdevices:
|
||||
"""handle all blockdevices of this system
|
||||
"""
|
||||
|
||||
def __init__(self, sysblock_dir='/sys/block', devnode_dir='/dev'):
|
||||
def __init__(self,
|
||||
sysblock_dir=DEFAULT_SYSBLOCK_DIR,
|
||||
devnode_dir=DEFAULT_DEVNODE_DIR):
|
||||
self.sysblock_dir = sysblock_dir
|
||||
self.devnode_dir = devnode_dir
|
||||
self.devices = []
|
||||
for devdir in find_blockdevices(self.sysblock_dir):
|
||||
blockdevice = Blockdevice(devdir, self.devnode_dir)
|
||||
if not blockdevice is None:
|
||||
blockdevice = get_blockdevice(devdir,
|
||||
self.sysblock_dir, self.devnode_dir)
|
||||
if (not blockdevice is None) and blockdevice.is_valid():
|
||||
self.devices.append(blockdevice)
|
||||
|
||||
|
||||
|
@ -55,60 +73,197 @@ class Blockdevices:
|
|||
|
||||
|
||||
|
||||
|
||||
class Blockdevice:
|
||||
|
||||
def __init__(self, dev, devnode_dir='/dev', sysblock_dir='/sys/block'):
|
||||
def __init__(self, dev,
|
||||
sysblock_dir=DEFAULT_SYSBLOCK_DIR,
|
||||
devnode_dir=DEFAULT_DEVNODE_DIR):
|
||||
"""initialize the blockdevice
|
||||
"""
|
||||
self.devdir = dev
|
||||
self.devnode_dir = devnode_dir
|
||||
self.sysblock_dir = sysblock_dir
|
||||
if os.path.isabs(dev):
|
||||
self.devdir = dev
|
||||
else:
|
||||
self.devdir = self.__find_relative_device(dev)
|
||||
if self.devdir is None:
|
||||
self = None
|
||||
return
|
||||
self.name = os.path.basename(self.devdir)
|
||||
self.devnum = self.__get_major_minor()
|
||||
## check valid devnum
|
||||
try:
|
||||
major, minor = self.devnum
|
||||
except TypeError:
|
||||
self = None
|
||||
return
|
||||
self.size = self.__get_size()
|
||||
self.range = self.__get_device_range()
|
||||
self.slaves = self.__get_dev_related("slaves")
|
||||
self.holders = self.__get_dev_related("holders")
|
||||
self.children = self.__get_children()
|
||||
self.devnodes = self.__get_device_nodes()
|
||||
|
||||
|
||||
def isstorage(self):
|
||||
if self.range > 1:
|
||||
## partitionable blockdevice
|
||||
def is_valid(self):
|
||||
""" check if the device is usable and valid
|
||||
"""
|
||||
if not self.devnodes:
|
||||
return False
|
||||
if self.size < 20:
|
||||
## extended partition, unused loop device
|
||||
return False
|
||||
if self.devnum[0] == 1:
|
||||
## ram device
|
||||
return False
|
||||
if self.children:
|
||||
## a parent blockdevice
|
||||
## check valid devnum
|
||||
try:
|
||||
major, minor = self.devnum
|
||||
if (major == 0) and (minor == 0):
|
||||
return False
|
||||
## ram devices are ignored
|
||||
if major == MAJOR_DEVNUM_RAM:
|
||||
return False
|
||||
## loop devices are ignored
|
||||
if major == MAJOR_DEVNUM_LOOP:
|
||||
return False
|
||||
except TypeError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def ispartitionable(self):
|
||||
def is_storage(self):
|
||||
"""return if this device can be used as a storage
|
||||
"""
|
||||
## check the cache first
|
||||
cache_link = ["blockdevice_info", self.name, "is_storage"]
|
||||
cached = _get_cached_value(cache_link)
|
||||
if not cached is None:
|
||||
return cached
|
||||
|
||||
if self.range > 1:
|
||||
## partitionable blockdevice
|
||||
_set_cached_value(cache_link, False)
|
||||
return False
|
||||
if self.size < MINIMUM_STORAGE_SIZE:
|
||||
## extended partition, unused loop device
|
||||
_set_cached_value(cache_link, False)
|
||||
return False
|
||||
if self.devnum[0] == MAJOR_DEVNUM_RAM:
|
||||
## ram device
|
||||
_set_cached_value(cache_link, False)
|
||||
return False
|
||||
## are we the device mapper of a luks device?
|
||||
for slave in self.slaves:
|
||||
if get_blockdevice(slave, self.sysblock_dir,
|
||||
self.devnode_dir).is_luks():
|
||||
_set_cached_value(cache_link, False)
|
||||
return False
|
||||
## if we are a luks device with exactly one child, then
|
||||
## we are a storage
|
||||
if (len(self.children) == 1) and self.is_luks():
|
||||
_set_cached_value(cache_link, True)
|
||||
return True
|
||||
if self.children:
|
||||
## a parent blockdevice
|
||||
_set_cached_value(cache_link, False)
|
||||
return False
|
||||
_set_cached_value(cache_link, True)
|
||||
return True
|
||||
|
||||
|
||||
def is_partitionable(self):
|
||||
"""is the device partitionable
|
||||
"""
|
||||
if self.range > 1:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def __find_relative_device(self, devname):
|
||||
for devdir in find_blockdevices(self.sysblock_dir):
|
||||
if os.path.basename(devdir) == devname:
|
||||
return devdir
|
||||
return None
|
||||
def is_lvm_pv(self):
|
||||
"""return if the device is a physical volume of a LVM
|
||||
"""
|
||||
## check the cache first
|
||||
cache_link = ["blockdevice_info", self.name, "is_lvm_pv"]
|
||||
cached = _get_cached_value(cache_link)
|
||||
if not cached is None:
|
||||
return cached
|
||||
|
||||
## is one of the devnodes of the device a physical volume?
|
||||
for one_lvm_pv in find_lvm_pv():
|
||||
if one_lvm_pv in self.devnodes:
|
||||
_set_cached_value(cache_link, True)
|
||||
return True
|
||||
_set_cached_value(cache_link, False)
|
||||
return False
|
||||
|
||||
|
||||
def is_lvm_lv(self):
|
||||
"""return if the device is a logical volume of a LVM
|
||||
"""
|
||||
## check the cache first
|
||||
cache_link = ["blockdevice_info", self.name, "is_lvm_lv"]
|
||||
cached = _get_cached_value(cache_link)
|
||||
if not cached is None:
|
||||
return cached
|
||||
|
||||
## is one of the devnodes of the device a physical volume?
|
||||
## logical LVM volumes always depend on their physical volumes
|
||||
if not self.slaves:
|
||||
_set_cached_value(cache_link, False)
|
||||
return False
|
||||
## is one of the LVM physical volumes a device node of our slave(s)?
|
||||
for one_lvm_pv in find_lvm_pv():
|
||||
for one_slave in self.slaves:
|
||||
if one_lvm_pv in get_blockdevice(one_slave,
|
||||
self.sysblock_dir, self.devnode_dir).devnodes:
|
||||
_set_cached_value(cache_link, True)
|
||||
return True
|
||||
_set_cached_value(cache_link, False)
|
||||
return False
|
||||
|
||||
|
||||
def is_md_raid(self):
|
||||
"""check if the device is the base of a md raid device
|
||||
"""
|
||||
## check the cache first
|
||||
cache_link = ["blockdevice_info", self.name, "is_md_raid"]
|
||||
cached = _get_cached_value(cache_link)
|
||||
if not cached is None:
|
||||
return cached
|
||||
|
||||
if self.range > 1:
|
||||
result = False
|
||||
elif self.size < MINIMUM_STORAGE_SIZE:
|
||||
result = False
|
||||
else:
|
||||
for hold in self.holders:
|
||||
if get_blockdevice(hold, self.sysblock_dir,
|
||||
self.devnode_dir).devnum[0] == MAJOR_DEVNUM_MD_RAID:
|
||||
result = True
|
||||
break
|
||||
else:
|
||||
result = False
|
||||
|
||||
## store result and return
|
||||
_set_cached_value(cache_link, result)
|
||||
return result
|
||||
|
||||
|
||||
def is_luks(self):
|
||||
"""check if the device is a luks container
|
||||
"""
|
||||
## check the cache first
|
||||
cache_link = ["blockdevice_info", self.name, "is_luks"]
|
||||
cached = _get_cached_value(cache_link)
|
||||
if not cached is None:
|
||||
return cached
|
||||
|
||||
if self.range > 1:
|
||||
result = False
|
||||
elif self.size < MINIMUM_STORAGE_SIZE:
|
||||
result = False
|
||||
elif self.is_lvm_pv():
|
||||
result = False
|
||||
elif self.is_md_raid():
|
||||
result = False
|
||||
else:
|
||||
## is the device a luks volume?
|
||||
prefs = _load_preferences()
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE,
|
||||
args = [ prefs["Programs"]["cryptsetup"],
|
||||
"--batch-mode", "isLuks", self.devnodes[0]])
|
||||
proc.wait()
|
||||
result = proc.returncode == 0
|
||||
## store result and return
|
||||
_set_cached_value(cache_link, result)
|
||||
return result
|
||||
|
||||
|
||||
def __get_dev_related(self, subdir):
|
||||
|
@ -121,6 +276,8 @@ class Blockdevice:
|
|||
|
||||
|
||||
def __get_size(self):
|
||||
"""return the size (in kB) of the blockdevice
|
||||
"""
|
||||
default = 0
|
||||
try:
|
||||
return int(file(os.path.join(self.devdir, 'size')).read())
|
||||
|
@ -132,12 +289,15 @@ class Blockdevice:
|
|||
|
||||
def __get_major_minor(self):
|
||||
"""return the major and minor of the device"""
|
||||
default = (0 ,0)
|
||||
default = (0, 0)
|
||||
try:
|
||||
content = file(os.path.join(self.devdir, "dev")).read()
|
||||
except IOError:
|
||||
return default
|
||||
major, minor = content.split(":", 2)
|
||||
try:
|
||||
major, minor = content.split(":", 1)
|
||||
except TypeError:
|
||||
return default
|
||||
try:
|
||||
return int(major), int(minor)
|
||||
except ValueError:
|
||||
|
@ -165,20 +325,48 @@ class Blockdevice:
|
|||
|
||||
all holders, subdevices and children of subdevices
|
||||
"""
|
||||
direct_children = [Blockdevice(child).name
|
||||
direct_children = [
|
||||
get_blockdevice(child, self.sysblock_dir, self.devnode_dir).name
|
||||
for child in find_blockdevices(self.devdir)]
|
||||
direct_children.extend(self.holders[:])
|
||||
children = direct_children[:]
|
||||
for dchild in direct_children:
|
||||
children.extend(Blockdevice(dchild).children)
|
||||
children.extend(get_blockdevice(dchild, self.sysblock_dir,
|
||||
self.devnode_dir).children)
|
||||
return children
|
||||
|
||||
|
||||
def __get_device_nodes(self):
|
||||
"""get all device nodes with the major/minor combination of the device
|
||||
"""
|
||||
result = []
|
||||
major, minor = self.devnum
|
||||
|
||||
def find_major_minor(arg, dirname, fnames):
|
||||
for fname in fnames:
|
||||
try:
|
||||
stat = os.stat(os.path.join(dirname, fname))
|
||||
## check if it is a blockdevice and compare major/minor
|
||||
if (stat.st_mode & 060000 == 060000) \
|
||||
and (os.major(stat.st_rdev) == major) \
|
||||
and (os.minor(stat.st_rdev) == minor):
|
||||
result.append(os.path.join(dirname, fname))
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
os.path.walk(self.devnode_dir, find_major_minor, None)
|
||||
return result
|
||||
|
||||
|
||||
def __str__(self):
|
||||
"""display the name of the device
|
||||
"""
|
||||
return self.name
|
||||
|
||||
|
||||
def info(self):
|
||||
"""display some information about the device
|
||||
"""
|
||||
output = "%s:\n" % self.name
|
||||
output += "\t%s:\t%s\n" % ("blockdir", self.devdir)
|
||||
output += "\t%s:\t%s\n" % ("major/minor", self.devnum)
|
||||
|
@ -187,12 +375,45 @@ class Blockdevice:
|
|||
output += "\t%s:\t\t%s\n" % ("slaves", self.slaves)
|
||||
output += "\t%s:\t%s\n" % ("holders", self.holders)
|
||||
output += "\t%s:\t%s\n" % ("children", self.children)
|
||||
output += "\t%s:\t%s\n" % ("device nodes", self.devnodes)
|
||||
output += "\tflags:\t\t"
|
||||
for funcname in [ "storage", "md_raid", "partitionable", "luks",
|
||||
"lvm_pv", "lvm_lv"]:
|
||||
if getattr(self, "is_%s" % funcname)():
|
||||
output += "%s " % funcname
|
||||
output += "\n"
|
||||
return output
|
||||
|
||||
|
||||
def get_blockdevice(dev,
|
||||
sysblock_dir=DEFAULT_SYSBLOCK_DIR,
|
||||
devnode_dir=DEFAULT_DEVNODE_DIR):
|
||||
if os.path.isabs(dev):
|
||||
if os.path.isfile(os.path.join(dev, "dev")):
|
||||
devdir = dev
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
for one_devdir in find_blockdevices(sysblock_dir):
|
||||
if os.path.basename(one_devdir) == dev:
|
||||
devdir = one_devdir
|
||||
break
|
||||
else:
|
||||
return None
|
||||
devname = os.path.basename(devdir)
|
||||
dev = _get_cached_value(["blockdevices", devname])
|
||||
if dev is None:
|
||||
dev = Blockdevice(devdir, sysblock_dir, devnode_dir)
|
||||
_set_cached_value(["blockdevices", devname], dev)
|
||||
return dev
|
||||
|
||||
|
||||
def find_blockdevices(top_dir):
|
||||
|
||||
cached = _get_cached_value(["blockdevice_dirs", top_dir])
|
||||
if not cached is None:
|
||||
return cached[:]
|
||||
|
||||
dev_dirs = []
|
||||
|
||||
def look4dev_dirs(arg, dirname, fnames):
|
||||
|
@ -210,21 +431,141 @@ def find_blockdevices(top_dir):
|
|||
fnames.remove(fname)
|
||||
|
||||
os.path.walk(top_dir, look4dev_dirs, 'dev')
|
||||
return dev_dirs
|
||||
_set_cached_value(["blockdevice_dirs", top_dir], dev_dirs)
|
||||
return dev_dirs[:]
|
||||
|
||||
|
||||
def find_lvm_pv():
|
||||
"""return the blockdevice names of all physical LVM volumes
|
||||
"""
|
||||
cached = _get_cached_value(["lvm", "pv"])
|
||||
if not cached is None:
|
||||
return cached[:]
|
||||
|
||||
#TODO: should we check, if LVM is supported at all?
|
||||
# e.g. by checking the existence of pvdisplay?
|
||||
prefs = _load_preferences()
|
||||
result = None
|
||||
try:
|
||||
proc = subprocess.Popen(
|
||||
shell = False,
|
||||
stdout = subprocess.PIPE,
|
||||
args = [ prefs["Programs"]["super"],
|
||||
prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"program", "pvdisplay" ])
|
||||
proc.wait()
|
||||
except OSError, err_msg:
|
||||
# TODO: add a logging warning
|
||||
result = []
|
||||
if proc.returncode != 0:
|
||||
# TODO: add a logging warning
|
||||
result = []
|
||||
if result is None:
|
||||
result = []
|
||||
for line in proc.stdout.readlines():
|
||||
result.append(line.split(":", 1)[0].strip())
|
||||
_set_cached_value(["lvm", "pv"], result)
|
||||
return result[:]
|
||||
|
||||
|
||||
def _get_cached_value(link):
|
||||
"""return a cached value
|
||||
|
||||
"link" is an array of the hierachie of the accessed item
|
||||
e.g. link = ["blockdevices", "hda"]
|
||||
return None if the value is not in the cache or if USE_CACHE is False
|
||||
"""
|
||||
if not USE_CACHE:
|
||||
return None
|
||||
|
||||
if "expires" in CACHED_VALUES:
|
||||
if CACHED_VALUES["expires"] < int(time.time()):
|
||||
reset_cache()
|
||||
else:
|
||||
__reset_cache_timer()
|
||||
|
||||
ref = CACHED_VALUES
|
||||
for element in link:
|
||||
if element in ref:
|
||||
ref = ref[element]
|
||||
else:
|
||||
return None
|
||||
return ref
|
||||
|
||||
|
||||
def reset_cache():
|
||||
## refresh the cache
|
||||
for item in CACHED_VALUES:
|
||||
CACHED_VALUES[item] = {}
|
||||
__reset_cache_timer()
|
||||
|
||||
|
||||
def __reset_cache_timer():
|
||||
CACHED_VALUES["expires"] = int(time.time()) + CACHE_EXPIRE_SECONDS
|
||||
|
||||
|
||||
|
||||
def _set_cached_value(link, item):
|
||||
"""store an item in the cache
|
||||
|
||||
"link" is an array of the hierachie of the accessed item
|
||||
e.g. link = ["blockdevices", "hda"]
|
||||
"""
|
||||
if not USE_CACHE:
|
||||
return
|
||||
ref = CACHED_VALUES
|
||||
for element in link[:-1]:
|
||||
if not element in ref:
|
||||
## create a non-existing sub element
|
||||
ref[element] = {}
|
||||
ref = ref[element]
|
||||
## store the item
|
||||
ref[link[-1]] = item
|
||||
|
||||
|
||||
def _load_preferences():
|
||||
prefs = cryptobox.core.settings.get_current_settings()
|
||||
if not prefs is None:
|
||||
## now the preferences are loaded
|
||||
return prefs
|
||||
## we have to load an emergency fallback for proper function
|
||||
## this is mainly useful for local testing
|
||||
root_dir = os.path.realpath(os.path.join(globals()["cryptobox"].__path__[0],
|
||||
os.path.pardir, os.path.pardir))
|
||||
config_file = os.path.join(root_dir, "bin", "cryptobox.conf")
|
||||
## we have to chdir to the 'bin' directory - otherwise the paths in
|
||||
## cryptobox.conf do not work
|
||||
os.chdir(os.path.dirname(config_file))
|
||||
return cryptobox.core.settings.CryptoBoxSettings(config_file)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
blocks = Blockdevices()
|
||||
for dev in blocks.get_devices():
|
||||
print dev.info()
|
||||
print
|
||||
print "Usable storage devices:"
|
||||
for dev in blocks.get_devices():
|
||||
if dev.isstorage():
|
||||
print dev
|
||||
print
|
||||
print "Partitionable devices:"
|
||||
for dev in blocks.get_devices():
|
||||
if dev.ispartitionable():
|
||||
print dev
|
||||
## list the properties of all available devices
|
||||
## this is just for testing purposes
|
||||
blocks = Blockdevices().get_devices()
|
||||
|
||||
## do we want to show the result?
|
||||
def show(text=""):
|
||||
if IS_VISIBLE:
|
||||
print text
|
||||
|
||||
if len(blocks) > 0:
|
||||
## show all devices and their properties
|
||||
show("Properties of all devices:")
|
||||
for device in blocks:
|
||||
show(device.info())
|
||||
|
||||
## discover all self-check methods
|
||||
example = blocks[0]
|
||||
flag_checker = [ method for method in dir(example)
|
||||
if callable(getattr(example, method))
|
||||
and method.startswith("is_")]
|
||||
## list all checks and the respective devices
|
||||
for check in flag_checker:
|
||||
show("List of '%s' devices:" % check[3:])
|
||||
for device in blocks:
|
||||
if getattr(device, check)():
|
||||
show("\t%s" % device)
|
||||
show()
|
||||
|
||||
|
|
|
@ -275,7 +275,7 @@ class CryptoBoxContainer:
|
|||
args = [
|
||||
self.cbox.prefs["Programs"]["super"],
|
||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"cryptsetup",
|
||||
"program", "cryptsetup",
|
||||
"luksAddKey",
|
||||
self.device,
|
||||
"--batch-mode"])
|
||||
|
@ -523,7 +523,7 @@ class CryptoBoxContainer:
|
|||
args = [
|
||||
self.cbox.prefs["Programs"]["super"],
|
||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"cryptsetup",
|
||||
"program", "cryptsetup",
|
||||
"luksOpen",
|
||||
self.device,
|
||||
self.name,
|
||||
|
@ -542,7 +542,7 @@ class CryptoBoxContainer:
|
|||
args = [
|
||||
self.cbox.prefs["Programs"]["super"],
|
||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"mount",
|
||||
"program", "mount",
|
||||
os.path.join(self.__dmDir, self.name),
|
||||
self.__get_mount_point()])
|
||||
proc.wait()
|
||||
|
@ -572,7 +572,7 @@ class CryptoBoxContainer:
|
|||
args = [
|
||||
self.cbox.prefs["Programs"]["super"],
|
||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"umount",
|
||||
"program", "umount",
|
||||
self.__get_mount_point()])
|
||||
proc.wait()
|
||||
if proc.returncode != 0:
|
||||
|
@ -588,7 +588,7 @@ class CryptoBoxContainer:
|
|||
args = [
|
||||
self.cbox.prefs["Programs"]["super"],
|
||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"cryptsetup",
|
||||
"program", "cryptsetup",
|
||||
"luksClose",
|
||||
self.name,
|
||||
"--batch-mode"])
|
||||
|
@ -620,7 +620,7 @@ class CryptoBoxContainer:
|
|||
args = [
|
||||
self.cbox.prefs["Programs"]["super"],
|
||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"mount",
|
||||
"program", "mount",
|
||||
self.device,
|
||||
self.__get_mount_point()])
|
||||
proc.wait()
|
||||
|
@ -653,7 +653,7 @@ class CryptoBoxContainer:
|
|||
args = [
|
||||
self.cbox.prefs["Programs"]["super"],
|
||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"umount",
|
||||
"program", "umount",
|
||||
self.__get_mount_point()])
|
||||
proc.wait()
|
||||
if proc.returncode != 0:
|
||||
|
@ -734,7 +734,7 @@ class CryptoBoxContainer:
|
|||
args = [
|
||||
self.cbox.prefs["Programs"]["super"],
|
||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"cryptsetup",
|
||||
"program", "cryptsetup",
|
||||
"luksFormat",
|
||||
self.device,
|
||||
"--batch-mode",
|
||||
|
@ -755,7 +755,7 @@ class CryptoBoxContainer:
|
|||
args = [
|
||||
self.cbox.prefs["Programs"]["super"],
|
||||
self.cbox.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"cryptsetup",
|
||||
"program", "cryptsetup",
|
||||
"luksOpen",
|
||||
self.device,
|
||||
self.name,
|
||||
|
|
|
@ -40,6 +40,19 @@ VOLUMESDB_FILE = "cryptobox_volumes.db"
|
|||
PLUGINCONF_FILE = "cryptobox_plugins.conf"
|
||||
USERDB_FILE = "cryptobox_users.db"
|
||||
|
||||
## allow to retrieve the most recently created setting object
|
||||
CURRENT_SETTING = []
|
||||
|
||||
|
||||
def get_current_settings():
|
||||
"""return the most recently created setting object
|
||||
"""
|
||||
if not CURRENT_SETTING:
|
||||
return None
|
||||
else:
|
||||
return CURRENT_SETTING[0]
|
||||
|
||||
|
||||
|
||||
class CryptoBoxSettings:
|
||||
"""Manage the various configuration files of the CryptoBox
|
||||
|
@ -63,6 +76,7 @@ class CryptoBoxSettings:
|
|||
self.misc_files = []
|
||||
self.reload_misc_files()
|
||||
self.__is_initialized = True
|
||||
CURRENT_SETTING.insert(0, self)
|
||||
|
||||
|
||||
def reload_misc_files(self):
|
||||
|
@ -190,7 +204,7 @@ class CryptoBoxSettings:
|
|||
args = [
|
||||
self.prefs["Programs"]["super"],
|
||||
self.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"mount",
|
||||
"program", "mount",
|
||||
"_tmpfs_",
|
||||
mount_dir ])
|
||||
(stdout, stderr) = proc.communicate()
|
||||
|
@ -211,7 +225,7 @@ class CryptoBoxSettings:
|
|||
args = [
|
||||
self.prefs["Programs"]["super"],
|
||||
self.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"mount",
|
||||
"program", "mount",
|
||||
partition,
|
||||
mount_dir ])
|
||||
(stdout, stderr) = proc.communicate()
|
||||
|
@ -241,7 +255,7 @@ class CryptoBoxSettings:
|
|||
args = [
|
||||
self.prefs["Programs"]["super"],
|
||||
self.prefs["Programs"]["CryptoBoxRootActions"],
|
||||
"umount",
|
||||
"program", "umount",
|
||||
mount_dir ])
|
||||
(stdout, stderr) = proc.communicate()
|
||||
if proc.returncode != 0:
|
||||
|
|
Loading…
Reference in a new issue