Lars' poland path #2
This commit is contained in:
parent
175cb831ad
commit
f450e116a7
8 changed files with 173 additions and 220 deletions
|
@ -21,6 +21,7 @@ import os
|
||||||
import unittest
|
import unittest
|
||||||
import logging
|
import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from CryptoBoxExceptions import *
|
||||||
|
|
||||||
CONF_LOCATIONS = [
|
CONF_LOCATIONS = [
|
||||||
"./cryptobox.conf",
|
"./cryptobox.conf",
|
||||||
|
@ -34,11 +35,6 @@ class CryptoBox:
|
||||||
put things like logging, conf and oter stuff in here,
|
put things like logging, conf and oter stuff in here,
|
||||||
that might be used by more classes, it will be passed on to them'''
|
that might be used by more classes, it will be passed on to them'''
|
||||||
def __init__(self, config_file=None):
|
def __init__(self, config_file=None):
|
||||||
# choose an exit function
|
|
||||||
if __name__ == "__main__":
|
|
||||||
self.errorExit = self.errorExitProg
|
|
||||||
else:
|
|
||||||
self.errorExit = self.errorExitMod
|
|
||||||
self.__initLogging()
|
self.__initLogging()
|
||||||
self.__initPreferences(config_file)
|
self.__initPreferences(config_file)
|
||||||
self.__runTests()
|
self.__runTests()
|
||||||
|
@ -65,14 +61,14 @@ class CryptoBox:
|
||||||
self.log.info("loggingsystem is up'n running")
|
self.log.info("loggingsystem is up'n running")
|
||||||
## from now on everything can be logged via self.log...
|
## from now on everything can be logged via self.log...
|
||||||
except:
|
except:
|
||||||
self.errorExit("SystemError","Couldn't initialise the loggingsystem. I give up.")
|
raise CBEnvironmentError("couldn't initialise the loggingsystem. I give up.")
|
||||||
|
|
||||||
|
|
||||||
def __initPreferences(self, config_file):
|
def __initPreferences(self, config_file):
|
||||||
try:
|
try:
|
||||||
import configobj ## needed for reading and writing of the config file
|
import configobj ## needed for reading and writing of the config file
|
||||||
except:
|
except:
|
||||||
self.errorExit("SystemError", "Couldn't import 'configobj'! Try 'apt-get install python-configobj'.")
|
raise CBEnvironmentError("couldn't import 'configobj'! Try 'apt-get install python-configobj'.")
|
||||||
# search for the configuration file
|
# search for the configuration file
|
||||||
if config_file is None:
|
if config_file is None:
|
||||||
# no config file was specified - we will look for it in the ususal locations
|
# no config file was specified - we will look for it in the ususal locations
|
||||||
|
@ -81,31 +77,29 @@ class CryptoBox:
|
||||||
if os.path.exists(os.path.expanduser(f))]
|
if os.path.exists(os.path.expanduser(f))]
|
||||||
if not conf_file_list:
|
if not conf_file_list:
|
||||||
# no possible config file found in the usual locations
|
# no possible config file found in the usual locations
|
||||||
self.errorExit("ConfigError", "No configuration file found - sorry!")
|
raise CBConfigUnavailableError()
|
||||||
config_file = conf_file_list[0]
|
config_file = conf_file_list[0]
|
||||||
else:
|
else:
|
||||||
# a config file was specified (e.g. via command line)
|
# a config file was specified (e.g. via command line)
|
||||||
if type(config_file) != types.StringType:
|
if type(config_file) != types.StringType:
|
||||||
self.errorExit("ConfigError","Invalid config file specified: %s" % config_file)
|
raise CBConfigUnavailableError("invalid config file specified: %s" % config_file)
|
||||||
if not os.path.exists(config_file):
|
if not os.path.exists(config_file):
|
||||||
self.errorExit("ConfigError","Could not find the specified configuration file (%s)" % config_file)
|
raise CBConfigUnavailableError("could not find the specified configuration file (%s)" % config_file)
|
||||||
try:
|
try:
|
||||||
self.cbxPrefs = configobj.ConfigObj(config_file)
|
self.cbxPrefs = configobj.ConfigObj(config_file)
|
||||||
if self.cbxPrefs:
|
if self.cbxPrefs:
|
||||||
self.log.info("found config: %s" % self.cbxPrefs.items())
|
self.log.info("found config: %s" % self.cbxPrefs.items())
|
||||||
else:
|
else:
|
||||||
self.errorExit("ConfigError","failed to load the config file: %s" % config_file)
|
raise CBConfigUnavailableError("failed to load the config file: %s" % config_file)
|
||||||
except IOError:
|
except IOError:
|
||||||
self.errorExit("ConfigError","unable to open the config file: %s" % config_file)
|
raise CBConfigUnavailableError("unable to open the config file: %s" % config_file)
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
nameDB_file = os.path.join(
|
nameDB_file = self.cbxPrefs["Locations"]["NameDatabase"]
|
||||||
self.cbxPrefs["Main"]["DataDir"],
|
|
||||||
self.cbxPrefs["Main"]["NameDatabase"])
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.errorExit("ConfigError","could not find one of these configuration settings: [Main]->DataDir and [Main]->NameDatabase - please check your config file(%s)" % config_file)
|
raise CBConfigUndefinedError("Locations", "NameDatabase")
|
||||||
except SyntaxError:
|
except SyntaxError:
|
||||||
self.errorExit("ConfigError","Error during parsing of name database file (%s).\n" % (nameDB_file, ))
|
raise CBConfigInvalidValueError("Locations", "NameDatabase", nameDB_file, "failed to interprete the filename of the name database correctly")
|
||||||
## create nameDB is necessary
|
## create nameDB is necessary
|
||||||
if os.path.exists(nameDB_file):
|
if os.path.exists(nameDB_file):
|
||||||
self.nameDB = configobj.ConfigObj(nameDB_file)
|
self.nameDB = configobj.ConfigObj(nameDB_file)
|
||||||
|
@ -113,54 +107,78 @@ class CryptoBox:
|
||||||
self.nameDB = configobj.ConfigObj(nameDB_file, create_empty=True)
|
self.nameDB = configobj.ConfigObj(nameDB_file, create_empty=True)
|
||||||
## check if nameDB file was created successfully?
|
## check if nameDB file was created successfully?
|
||||||
if not os.path.exists(nameDB_file):
|
if not os.path.exists(nameDB_file):
|
||||||
self.errorExit("ConfigError","failed to create name database (%s)" % nameDB_file)
|
raise CBEnvironmentError("failed to create name database (%s)" % nameDB_file)
|
||||||
# get the loglevel
|
# get the loglevel
|
||||||
try:
|
try:
|
||||||
log_level = self.cbxPrefs["Log"]["Level"].upper()
|
log_level = self.cbxPrefs["Log"]["Level"].upper()
|
||||||
log_level_avail = ["DEBUG", "INFO", "WARN", "ERROR"]
|
log_level_avail = ["DEBUG", "INFO", "WARN", "ERROR"]
|
||||||
if not log_level in log_level_avail:
|
if not log_level in log_level_avail:
|
||||||
self.errorExit("ConfigError","invalid log level: %s is not in %s" % (self.cbxPrefs["Log"]["Level"], log_level_avail))
|
raise TypeError
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.errorExit("ConfigError","could not find the configuration setting [Log]->Level in the config file (%s)" % config_file)
|
raise CBConfigUndefinedError("Log", "Level")
|
||||||
except TypeError:
|
except TypeError:
|
||||||
self.errorExit("ConfigError","invalid log level: %s" % self.cbxPrefs["Log"]["Level"])
|
raise CBConfigInvalidValueError("Log", "Level", log_level, "invalid log level: only %s are allowed" % log_level_avail)
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
new_handler = logging.FileHandler(self.cbxPrefs["Log"]["Details"])
|
new_handler = logging.FileHandler(self.cbxPrefs["Log"]["Details"])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.errorExit("ConfigError","could not find a configuration setting: [Log]->Details - please check your config file(%s)" % config_file)
|
raise CBConfigUndefinedError("Log", "Details")
|
||||||
new_handler.setFormatter(logging.Formatter('%(asctime)s %(module)s %(levelname)s: %(message)s'))
|
|
||||||
self.log.addHandler(new_handler)
|
|
||||||
## do not call parent's handlers
|
|
||||||
self.log.propagate = False
|
|
||||||
## use 'getattr' as 'log_level' is a string
|
|
||||||
self.log.setLevel(getattr(logging,log_level))
|
|
||||||
except IOError:
|
except IOError:
|
||||||
self.errorExit("ConfigError","could not open logfile: %s" % self.cbxPrefs["Log"]["Details"])
|
raise CBEnvironmentError("could not create the log file (%s)" % self.cbxPrefs["Log"]["Details"])
|
||||||
|
new_handler.setFormatter(logging.Formatter('%(asctime)s %(module)s %(levelname)s: %(message)s'))
|
||||||
|
self.log.addHandler(new_handler)
|
||||||
|
## do not call parent's handlers
|
||||||
|
self.log.propagate = False
|
||||||
|
## 'log_level' is a string -> use 'getattr'
|
||||||
|
self.log.setLevel(getattr(logging,log_level))
|
||||||
|
|
||||||
|
|
||||||
# do some initial checks
|
# do some initial checks
|
||||||
def __runTests(self):
|
def __runTests(self):
|
||||||
## try to run 'super' with 'CryptoBoxRootActions'
|
self.__runTestRootPriv()
|
||||||
|
self.__runTestLocations()
|
||||||
|
|
||||||
|
|
||||||
|
def __runTestLocations(self):
|
||||||
|
"""check if all configured locations exist"""
|
||||||
|
try:
|
||||||
|
conf_locations = self.cbxPrefs["Locations"]
|
||||||
|
except KeyError:
|
||||||
|
raise CBConfigUndefinedError("Locations")
|
||||||
|
try:
|
||||||
|
for key in ["MountParentDir", "NameDatabase", "TemplateDir", "LangDir", "DocDir"]:
|
||||||
|
value = self.cbxPrefs["Locations"][key]
|
||||||
|
#if not (os.path.exists(value) and os.access(value, os.R_OK)):
|
||||||
|
if not os.access(value, os.R_OK):
|
||||||
|
raise CBConfigInvalidValueError("Locations", key, value, "could not access")
|
||||||
|
except KeyError:
|
||||||
|
raise CBConfigUndefinedError("Locations", key)
|
||||||
|
|
||||||
|
def __runTestRootPriv(self):
|
||||||
|
"""try to run 'super' with 'CryptoBoxRootActions'"""
|
||||||
try:
|
try:
|
||||||
devnull = open(os.devnull, "w")
|
devnull = open(os.devnull, "w")
|
||||||
except IOError:
|
except IOError:
|
||||||
self.errorExit("SystemError","Could not open %s for writing!" % os.devnull)
|
raise CBEnvironmentError("could not open %s for writing!" % os.devnull)
|
||||||
|
try:
|
||||||
|
prog_super = self.cbxPrefs["Programs"]["super"]
|
||||||
|
except KeyError:
|
||||||
|
raise CBConfigUndefinedError("Programs", "super")
|
||||||
|
try:
|
||||||
|
prog_rootactions = self.cbxPrefs["Programs"]["CryptoBoxRootActions"]
|
||||||
|
except KeyError:
|
||||||
|
raise CBConfigUndefinedError("Programs", "CryptoBoxRootActions")
|
||||||
try:
|
try:
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
shell = False,
|
shell = False,
|
||||||
stdout = devnull,
|
stdout = devnull,
|
||||||
stderr = devnull,
|
stderr = devnull,
|
||||||
args = [ self.cbxPrefs["Programs"]["super"],
|
args = [prog_super, prog_rootactions, "check"])
|
||||||
self.cbxPrefs["Programs"]["CryptoBoxRootActions"],
|
|
||||||
"check"])
|
|
||||||
except OSError:
|
except OSError:
|
||||||
self.errorExit("ConfigError","could not find: %s" % self.cbxPrefs["Programs"]["super"])
|
raise CBEnvironmentError("failed to execute 'super' (%s)" % self.cbxPrefs["Programs"]["super"])
|
||||||
except KeyError:
|
|
||||||
self.errorExit("ConfigError","could not find one of these configurations settings: [Programs]->super or [Programs]->CryptoBoxRootActions in the config file")
|
|
||||||
proc.wait()
|
proc.wait()
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
self.errorExit("ConfigError","Could not call CryptoBoxRootActions by 'super' - maybe you did not add the appropriate line to /etc/super.tab?")
|
raise CBEnvironmentError("failed to call CryptoBoxRootActions (%s) via 'super' - maybe you did not add the appropriate line to /etc/super.tab?" % prog_rootactions)
|
||||||
|
|
||||||
|
|
||||||
# this method just demonstrates inheritance effects - may be removed
|
# this method just demonstrates inheritance effects - may be removed
|
||||||
|
@ -168,27 +186,6 @@ class CryptoBox:
|
||||||
self.log.info(string)
|
self.log.info(string)
|
||||||
|
|
||||||
|
|
||||||
def errorExitMod(self, title, msg, code=1):
|
|
||||||
"""output an error message and quit by raising an exception
|
|
||||||
|
|
||||||
this function should be used if this class was used as a module instead
|
|
||||||
of as a standalone program
|
|
||||||
"""
|
|
||||||
self.log.error(msg)
|
|
||||||
raise title, msg
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def errorExitProg(self, title, msg, code=1):
|
|
||||||
"""output an error message and quit by calling sys.exit
|
|
||||||
|
|
||||||
this function should be used if this class was used as a standalone
|
|
||||||
program
|
|
||||||
"""
|
|
||||||
self.log.error(msg)
|
|
||||||
sys.exit(code)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# RFC: why should CryptoBoxProps inherit CryptoBox? [l]
|
# RFC: why should CryptoBoxProps inherit CryptoBox? [l]
|
||||||
# RFC: shouldn't we move all useful functions of CryptoBoxProps to CryptoBox? [l]
|
# RFC: shouldn't we move all useful functions of CryptoBoxProps to CryptoBox? [l]
|
||||||
|
@ -230,13 +227,12 @@ class CryptoBoxProps(CryptoBox):
|
||||||
the maximum number and size of these entries can be limited by 'lines' and 'maxSize'
|
the maximum number and size of these entries can be limited by 'lines' and 'maxSize'
|
||||||
"""
|
"""
|
||||||
# return nothing if the currently selected log output is not a file
|
# return nothing if the currently selected log output is not a file
|
||||||
empty = [""]
|
|
||||||
try:
|
try:
|
||||||
if self.cbxPrefs["Log"]["Destination"].upper() != "FILE": return empty
|
if self.cbxPrefs["Log"]["Destination"].upper() != "FILE": return []
|
||||||
log_file = self.cbxPrefs["Log"]["Details"]
|
log_file = self.cbxPrefs["Log"]["Details"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.log.error("could not evaluate one of the following config settings: [Log]->Destination or [Log]->Details")
|
self.log.error("could not evaluate one of the following config settings: [Log]->Destination or [Log]->Details")
|
||||||
return empty
|
return []
|
||||||
try:
|
try:
|
||||||
fd = open(log_file, "r")
|
fd = open(log_file, "r")
|
||||||
if maxSize: content = fd.readlines(maxSize)
|
if maxSize: content = fd.readlines(maxSize)
|
||||||
|
@ -244,7 +240,7 @@ class CryptoBoxProps(CryptoBox):
|
||||||
fd.close()
|
fd.close()
|
||||||
except IOError:
|
except IOError:
|
||||||
self.log.warn("failed to read the log file (%s)" % log_file)
|
self.log.warn("failed to read the log file (%s)" % log_file)
|
||||||
return empty
|
return []
|
||||||
if lines: content = content[-lines:]
|
if lines: content = content[-lines:]
|
||||||
return content
|
return content
|
||||||
|
|
||||||
|
|
|
@ -293,7 +293,7 @@ class CryptoBoxContainer:
|
||||||
|
|
||||||
def __getMountPoint(self):
|
def __getMountPoint(self):
|
||||||
"return the name of the mountpoint of this volume"
|
"return the name of the mountpoint of this volume"
|
||||||
return os.path.join(self.cbox.cbxPrefs["System"]["MountParentDir"], self.name)
|
return os.path.join(self.cbox.cbxPrefs["Locations"]["MountParentDir"], self.name)
|
||||||
|
|
||||||
|
|
||||||
def __mountLuks(self, password):
|
def __mountLuks(self, password):
|
||||||
|
@ -559,9 +559,9 @@ class CryptoBoxContainer:
|
||||||
def __cleanMountDirs(self):
|
def __cleanMountDirs(self):
|
||||||
""" remove all unnecessary subdirs of the mount parent directory
|
""" remove all unnecessary subdirs of the mount parent directory
|
||||||
this should be called for every (u)mount """
|
this should be called for every (u)mount """
|
||||||
subdirs = os.listdir(self.cbox.cbxPrefs["System"]["MountParentDir"])
|
subdirs = os.listdir(self.cbox.cbxPrefs["Locations"]["MountParentDir"])
|
||||||
for dir in subdirs:
|
for dir in subdirs:
|
||||||
abs_dir = os.path.join(self.cbox.cbxPrefs["System"]["MountParentDir"], dir)
|
abs_dir = os.path.join(self.cbox.cbxPrefs["Locations"]["MountParentDir"], dir)
|
||||||
if (not os.path.islink(abs_dir)) and os.path.isdir(abs_dir) and (not os.path.ismount(abs_dir)):
|
if (not os.path.islink(abs_dir)) and os.path.isdir(abs_dir) and (not os.path.ismount(abs_dir)):
|
||||||
os.rmdir(abs_dir)
|
os.rmdir(abs_dir)
|
||||||
|
|
||||||
|
|
|
@ -44,20 +44,9 @@ def isWriteable(device, force_dev_type=None):
|
||||||
if dev_type != force_dev_type: return False
|
if dev_type != force_dev_type: return False
|
||||||
# retrieve the information for the real user id
|
# retrieve the information for the real user id
|
||||||
(trustUserName, trustUID, groupsOfTrustUser) = getUserInfo(os.getuid())
|
(trustUserName, trustUID, groupsOfTrustUser) = getUserInfo(os.getuid())
|
||||||
trustGIDs = []
|
|
||||||
try:
|
|
||||||
"if 'allowedGroups' are defined, then ignore the previously aquired groups"
|
|
||||||
"TODO: for now only group ids (no names) are allowed"
|
|
||||||
trustGIDs.extend(allowedGroups)
|
|
||||||
except NameError:
|
|
||||||
"'allowedGroups' was not defined - we use the default ones of the user"
|
|
||||||
trustGIDs.extend(groupsOfTrustUser)
|
|
||||||
except TypeError:
|
|
||||||
"if it fails, then 'allowedGroups' was really not well defined"
|
|
||||||
trustGIDs.append(allowedGID)
|
|
||||||
# set the default groups of the caller for the check (restore them later)
|
# set the default groups of the caller for the check (restore them later)
|
||||||
savedGroups = os.getgroups()
|
savedGroups = os.getgroups()
|
||||||
os.setgroups(trustGIDs)
|
os.setgroups(groupsOfTrustUser)
|
||||||
# check permissions
|
# check permissions
|
||||||
result = os.access(device, os.W_OK) and os.access(device, os.R_OK)
|
result = os.access(device, os.W_OK) and os.access(device, os.R_OK)
|
||||||
# reset the groups of this process
|
# reset the groups of this process
|
||||||
|
|
|
@ -19,12 +19,12 @@ class CryptoBoxWebserverRender:
|
||||||
|
|
||||||
website.log.info("rendering site: "+website.settings["Data.Action"])
|
website.log.info("rendering site: "+website.settings["Data.Action"])
|
||||||
|
|
||||||
cs_path = website.cbxPrefs["Settings"]["TemplateDir"]+"/main.cs"
|
cs_path = website.cbxPrefs["Locations"]["TemplateDir"]+"/main.cs"
|
||||||
if not os.access(cs_path, os.R_OK):
|
if not os.access(cs_path, os.R_OK):
|
||||||
website.log.error("Couldn't read cs file: %s" % cs_path)
|
website.log.error("Couldn't read cs file: %s" % cs_path)
|
||||||
return "Couldn't read cs file: %s" % cs_path
|
return "Couldn't read cs file: %s" % cs_path
|
||||||
|
|
||||||
hdf_path = website.cbxPrefs["Settings"]["LangDir"]+"/"+website.cbxPrefs["Settings"]["Language"]+".hdf"
|
hdf_path = website.cbxPrefs["Locations"]["LangDir"]+"/"+website.cbxPrefs["Settings"]["Language"]+".hdf"
|
||||||
if not os.access(hdf_path, os.R_OK):
|
if not os.access(hdf_path, os.R_OK):
|
||||||
website.log.error("Couldn't read hdf file: %s" % hdf_path)
|
website.log.error("Couldn't read hdf file: %s" % hdf_path)
|
||||||
return "Couldn't read hdf file: %s" % hdf_path
|
return "Couldn't read hdf file: %s" % hdf_path
|
||||||
|
|
|
@ -36,20 +36,21 @@ class CryptoBoxWebserverSites(CryptoBox.CryptoBoxProps, CryptoBoxWebserverSettin
|
||||||
sanitizing input automatically for all sites.
|
sanitizing input automatically for all sites.
|
||||||
# RFC: why shouldn't it be called in __init__? [l]
|
# RFC: why shouldn't it be called in __init__? [l]
|
||||||
'''
|
'''
|
||||||
#TODO: generate languages from existing hdf files
|
niceparams = { 'weblang': tuple(self.__getAvailableLanguages()),
|
||||||
niceparams = { 'weblang': ('', 'de', 'en'),
|
|
||||||
'loglevel': ('','info', 'warn', 'debug', 'error'),
|
'loglevel': ('','info', 'warn', 'debug', 'error'),
|
||||||
'type': ('reboot', 'poweroff')
|
'type': ('reboot', 'poweroff')
|
||||||
}
|
}
|
||||||
for evilkey in evilparams.keys():
|
for evilkey in evilparams.keys():
|
||||||
## if the param isn't in the niceparams list, ignore it
|
## if the param isn't in the niceparams list, ignore it
|
||||||
if not niceparams.get(evilkey):
|
if not niceparams.get(evilkey):
|
||||||
self.log.warn("ignoring \"%s\"" % evilkey)
|
self.log.warn('ignoring "%s"' % evilkey)
|
||||||
|
# RFC: why "return False"? - just ignoring is sufficient
|
||||||
return False
|
return False
|
||||||
#TODO: until now only a warning message is printed
|
#TODO: until now only a warning message is printed
|
||||||
## if the param has no such value, set it to a default (the first in the list)
|
## if the param has no such value, set it to a default (the first in the list)
|
||||||
if evilparams.get(evilkey) not in niceparams.get(evilkey):
|
if evilparams.get(evilkey) not in niceparams.get(evilkey):
|
||||||
self.log.warn("\"%s\" not in weblang %s"% (evilkey, niceparams.get(evilkey)))
|
self.log.warn('"%s" not in weblang %s' % (evilkey, niceparams.get(evilkey)))
|
||||||
|
# RFC: why "weblang"?
|
||||||
#TODO: set it to: niceparams.get(evilkey)[0]))
|
#TODO: set it to: niceparams.get(evilkey)[0]))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -63,6 +64,44 @@ class CryptoBoxWebserverSites(CryptoBox.CryptoBoxProps, CryptoBoxWebserverSettin
|
||||||
#TODO
|
#TODO
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def __getAvailableLanguages(self):
|
||||||
|
import re, os
|
||||||
|
regpat = re.compile(r"^\w+\.hdf$")
|
||||||
|
try:
|
||||||
|
lang_dir = self.cbxPrefs["Locations"]["LangDir"]
|
||||||
|
except KeyError:
|
||||||
|
self.log.error("Could not find a configuration setting: [Locations]->LangDir - please check the config file")
|
||||||
|
return []
|
||||||
|
if not os.path.exists(lang_dir):
|
||||||
|
self.log.error("The configured language directory (%s) does not exist" % (lang_dir, ))
|
||||||
|
return []
|
||||||
|
try:
|
||||||
|
return [ e[:-4] for e in os.listdir(lang_dir) if regpat.search(e)]
|
||||||
|
except OSError:
|
||||||
|
self.log.error("Could not access the language directory (%s)" % (lang_dir,))
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def __getAvailableDocLanguages(self):
|
||||||
|
import re, os
|
||||||
|
regpat = re.compile(r"^\w+$")
|
||||||
|
try:
|
||||||
|
doc_dir = self.cbxPrefs["Locations"]["DocDir"]
|
||||||
|
except KeyError:
|
||||||
|
self.log.error("Could not find a configuration setting: [Locations]->DocDir - please check the config file")
|
||||||
|
return []
|
||||||
|
if not os.path.exists(doc_dir):
|
||||||
|
self.log.error("The configured documentation directory (%s) does not exist" % (doc_dir, ))
|
||||||
|
return []
|
||||||
|
try:
|
||||||
|
return [ e for e in os.listdir(doc_dir)
|
||||||
|
if regpat.search(e) and os.path.isdir(os.path.join(doc_dir, e))]
|
||||||
|
except OSError:
|
||||||
|
self.log.error("Could not access the documentations directory (%s)" % (doc_dir,))
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
## put real sites down here and don't forget to expose them at the end
|
## put real sites down here and don't forget to expose them at the end
|
||||||
|
|
||||||
|
@ -78,10 +117,7 @@ class CryptoBoxWebserverSites(CryptoBox.CryptoBoxProps, CryptoBoxWebserverSettin
|
||||||
'''
|
'''
|
||||||
self.__sanitize_input({"loglevel":loglevel})
|
self.__sanitize_input({"loglevel":loglevel})
|
||||||
self.__prepare("show_log")
|
self.__prepare("show_log")
|
||||||
import filehandling
|
|
||||||
self.settings["Data.Log"] = "<br/>".join(self.getLogData(lines=30, maxSize=2000))
|
self.settings["Data.Log"] = "<br/>".join(self.getLogData(lines=30, maxSize=2000))
|
||||||
#TODO: give the logs a nice format for displaying as html
|
|
||||||
# sed s/$/<\/br>/
|
|
||||||
return website.render(self)
|
return website.render(self)
|
||||||
|
|
||||||
def status(self, weblang=""):
|
def status(self, weblang=""):
|
||||||
|
@ -117,11 +153,13 @@ class CryptoBoxWebserverSites(CryptoBox.CryptoBoxProps, CryptoBoxWebserverSettin
|
||||||
self.__prepare("show_doc")
|
self.__prepare("show_doc")
|
||||||
if page:
|
if page:
|
||||||
self.settings["Data.Doc.Page"] = page
|
self.settings["Data.Doc.Page"] = page
|
||||||
if page == "":
|
else:
|
||||||
self.settings["Data.Doc.Page"] ="CryptoBoxUser"
|
self.settings["Data.Doc.Page"] ="CryptoBoxUser"
|
||||||
if not weblang == "":
|
if weblang:
|
||||||
# TODO: check if there is a 'weblang' translation available for the docs
|
if weblang in self.__getAvailableDocLanguages():
|
||||||
self.settings["Settings.DocLang"] = weblang
|
self.settings["Settings.DocLang"] = weblang
|
||||||
|
else:
|
||||||
|
self.log.warn("invalid documentation language selected: %s", % (weblang, ))
|
||||||
return website.render(self)
|
return website.render(self)
|
||||||
|
|
||||||
|
|
||||||
|
@ -163,8 +201,8 @@ class CryptoBoxWebserverSites(CryptoBox.CryptoBoxProps, CryptoBoxWebserverSettin
|
||||||
#-------------------------------------------------------#
|
#-------------------------------------------------------#
|
||||||
################ umount_do #######################
|
################ umount_do #######################
|
||||||
elif action == "unmount_do":
|
elif action == "unmount_do":
|
||||||
if device == "":
|
if not device:
|
||||||
#TODO: debug message: "invalid device: "+ device
|
self.log.debug("invalid device chosen: %s" device
|
||||||
settings["Data.Warning"] = "InvalidDevice"
|
settings["Data.Warning"] = "InvalidDevice"
|
||||||
settings["Data.Action"] = "empty"
|
settings["Data.Action"] = "empty"
|
||||||
elif not True: #TODO: replace True with check_config()
|
elif not True: #TODO: replace True with check_config()
|
||||||
|
@ -187,10 +225,10 @@ class CryptoBoxWebserverSites(CryptoBox.CryptoBoxProps, CryptoBoxWebserverSettin
|
||||||
settings["Data.Action"] = "show_volume"
|
settings["Data.Action"] = "show_volume"
|
||||||
################ mount_do ########################
|
################ mount_do ########################
|
||||||
elif action == "mount_do":
|
elif action == "mount_do":
|
||||||
if device != "":
|
if device:
|
||||||
pass #TODO: is_encrypted = check_device_encryption(device)
|
pass #TODO: is_encrypted = check_device_encryption(device)
|
||||||
if device == "":
|
else:
|
||||||
#TODO: debug_msg(DEBUG_INFO, "invalid device: " + device)
|
self.log.debug("invalid device chosen: %s" device
|
||||||
settings["Data.Warning"] = "InvalidDevice"
|
settings["Data.Warning"] = "InvalidDevice"
|
||||||
settings["Data.Action"] = "empty"
|
settings["Data.Action"] = "empty"
|
||||||
elif not True: #TODO: replace True with check_config()
|
elif not True: #TODO: replace True with check_config()
|
||||||
|
@ -208,3 +246,4 @@ class CryptoBoxWebserverSites(CryptoBox.CryptoBoxProps, CryptoBoxWebserverSettin
|
||||||
system.exposed = True
|
system.exposed = True
|
||||||
status.exposed = True
|
status.exposed = True
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,38 +2,40 @@
|
||||||
|
|
||||||
# comma separated list of possible prefixes for accesible devices
|
# comma separated list of possible prefixes for accesible devices
|
||||||
# beware: .e.g "/dev/hd" grants access to _all_ harddisks
|
# beware: .e.g "/dev/hd" grants access to _all_ harddisks
|
||||||
AllowedDevices = /dev/loop
|
AllowedDevices = /dev/loop
|
||||||
|
|
||||||
# the default prefix of not yet named containers
|
# the default name prefix of not unnamed containers
|
||||||
|
DefaultVolumePrefix = "Data "
|
||||||
DefaultVolumePrefix = "Data "
|
|
||||||
|
|
||||||
# where should we put the local configuration and the mountpoints?
|
|
||||||
# this directory must be accessible by the cryptobox user (see below)
|
|
||||||
#DataDir = /var/cache/cryptobox
|
|
||||||
DataDir = .
|
|
||||||
|
|
||||||
# the name-database file - inside of DataDir
|
|
||||||
NameDatabase = cryptobox_names.db
|
|
||||||
|
|
||||||
|
|
||||||
[System]
|
|
||||||
# most actions of the cryptobox are not executed as root - choose a limited
|
|
||||||
# user and group here - for now only numeric ids are allowed
|
|
||||||
User = 1000
|
|
||||||
Group = 1000
|
|
||||||
|
|
||||||
# where should we mount volumes?
|
|
||||||
# this directory must be writeable by the cryptobox user (see above)
|
|
||||||
MountParentDir = /var/cache/cryptobox/mnt
|
|
||||||
|
|
||||||
# which cipher should cryptsetup-luks use?
|
# which cipher should cryptsetup-luks use?
|
||||||
DefaultCipher = aes-cbc-essiv:sha256
|
DefaultCipher = aes-cbc-essiv:sha256
|
||||||
|
|
||||||
|
|
||||||
|
[Locations]
|
||||||
|
# where should we mount volumes?
|
||||||
|
# this directory must be writeable by the cryptobox user (see above)
|
||||||
|
MountParentDir = /var/cache/cryptobox/mnt
|
||||||
|
|
||||||
|
# the name-database file - inside of DataDir
|
||||||
|
#NameDatabase = /var/cache/cryptobox/cryptobox_names.db
|
||||||
|
NameDatabase = cryptobox_names.db
|
||||||
|
|
||||||
|
# where are the clearsilver templates?
|
||||||
|
#TemplateDir = /usr/share/cryptobox/templates
|
||||||
|
TemplateDir = ../templates
|
||||||
|
|
||||||
|
# path to language files
|
||||||
|
#LangDir = /usr/share/cryptobox/lang
|
||||||
|
LangDir = ../lang
|
||||||
|
|
||||||
|
# path to documentation files
|
||||||
|
#DocDir = /usr/share/doc/cryptobox/html
|
||||||
|
DocDir = ../doc/html
|
||||||
|
|
||||||
|
|
||||||
[Log]
|
[Log]
|
||||||
# possible values are "debug", "info", "warn" and "error" or numbers from
|
# possible values are "debug", "info", "warn" and "error" or numbers from
|
||||||
# 0 (debug) to 9 (error)
|
# 0 (debug) to 7 (error)
|
||||||
Level = debug
|
Level = debug
|
||||||
|
|
||||||
# where to write the log messages to?
|
# where to write the log messages to?
|
||||||
|
@ -48,20 +50,18 @@ Destination = file
|
||||||
#Details = /var/log/cryptobox.log
|
#Details = /var/log/cryptobox.log
|
||||||
Details = ./cryptobox.log
|
Details = ./cryptobox.log
|
||||||
|
|
||||||
[Settings]
|
|
||||||
#default stylesheet
|
[WebSettings]
|
||||||
|
# URL of default stylesheet
|
||||||
Stylesheet = cryptobox.css
|
Stylesheet = cryptobox.css
|
||||||
#where are the clearsilver templates?
|
|
||||||
TemplateDir = ../templates
|
# default language
|
||||||
#path to language files
|
|
||||||
LangDir = ../lang
|
|
||||||
#default language
|
|
||||||
Language = de
|
Language = de
|
||||||
#path to documentation files
|
|
||||||
DocDir = ../doc/html
|
# default language for documentation
|
||||||
#default language for documentation
|
|
||||||
DocLang = de
|
DocLang = de
|
||||||
|
|
||||||
|
|
||||||
[Programs]
|
[Programs]
|
||||||
cryptsetup = /sbin/cryptsetup
|
cryptsetup = /sbin/cryptsetup
|
||||||
mkfs-data = /sbin/mkfs.ext3
|
mkfs-data = /sbin/mkfs.ext3
|
||||||
|
@ -70,6 +70,6 @@ blkid = /sbin/blkid
|
||||||
mount = /bin/mount
|
mount = /bin/mount
|
||||||
umount = /bin/umount
|
umount = /bin/umount
|
||||||
super = /usr/bin/super
|
super = /usr/bin/super
|
||||||
# this is the "program" name as defined in the /etc/super.tab
|
# this is the "program" name as defined in /etc/super.tab
|
||||||
CryptoBoxRootActions = CryptoBoxRootActions
|
CryptoBoxRootActions = CryptoBoxRootActions
|
||||||
|
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
import os,tempfile,dircache,string,commands
|
|
||||||
"""I suppose this stuff should be inside some class?"""
|
|
||||||
|
|
||||||
# RFC: which of these methods do we need more than once?
|
|
||||||
# or: these actions are too short for methods - or not? [l]
|
|
||||||
|
|
||||||
def read_file(filename):
|
|
||||||
"""
|
|
||||||
read from the file whose name is given
|
|
||||||
@param filename String : name of file to read from
|
|
||||||
@return String: content of given file or None
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
f = open(filename,"r")
|
|
||||||
filecontent = f.read()
|
|
||||||
f.close()
|
|
||||||
except:
|
|
||||||
#TODO:if debug >=1:
|
|
||||||
print "(EE)[%s]: \"%s\" is not readable!"%(__name__, filename)
|
|
||||||
return ""
|
|
||||||
return filecontent
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def is_dir_readable(path):
|
|
||||||
"""
|
|
||||||
Gets the name of a directory.
|
|
||||||
returns True if dir is readable, else False.
|
|
||||||
"""
|
|
||||||
return os.access(path,os.R_OK)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def write_file(filename,content):
|
|
||||||
"""
|
|
||||||
Write content to the given filename.
|
|
||||||
gets: filename,content.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
f = open(filename,"w")#oeffnen und schliessen =>
|
|
||||||
f.close() #datei ist jetzt genullt
|
|
||||||
f = open(filename,"a") #anhaengend oeffnen
|
|
||||||
f.write(content)
|
|
||||||
f.close()
|
|
||||||
return ""
|
|
||||||
except:
|
|
||||||
#TODO: debug
|
|
||||||
#if self.debug >=1:
|
|
||||||
print "(EE)[%s]: \"%s\" is not writeable!"%(__name__, filename)
|
|
||||||
return filename
|
|
||||||
|
|
||||||
def basename(filename):
|
|
||||||
return os.path.basename(filename)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def gen_temp_dir(prefix='cryptobox--'):
|
|
||||||
'''returns the name of a secure temporary directory
|
|
||||||
with optional prefix as parameter'''
|
|
||||||
dirname=tempfile.mkdtemp("",prefix)
|
|
||||||
dirname+="/"
|
|
||||||
return dirname
|
|
||||||
|
|
||||||
def gen_temp_file(suffix="--cryptobox"):
|
|
||||||
"""
|
|
||||||
returns the name of a generated temporay file.
|
|
||||||
optionally gets a suffix for the filename.
|
|
||||||
"""
|
|
||||||
return tempfile.mkstemp(suffix)[1]
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
import sys
|
import sys
|
||||||
|
from CryptoBox import *
|
||||||
|
|
||||||
class CryptoBoxPropsDeviceTests(unittest.TestCase):
|
class CryptoBoxPropsDeviceTests(unittest.TestCase):
|
||||||
import CryptoBox
|
import CryptoBox
|
||||||
|
@ -38,13 +39,13 @@ class CryptoBoxPropsConfigTests(unittest.TestCase):
|
||||||
[Main]
|
[Main]
|
||||||
AllowedDevices = /dev/loop
|
AllowedDevices = /dev/loop
|
||||||
DefaultVolumePrefix = "Data "
|
DefaultVolumePrefix = "Data "
|
||||||
DataDir = %s
|
|
||||||
NameDatabase = cryptobox_names.db
|
|
||||||
[System]
|
|
||||||
User = 1000
|
|
||||||
Group = 1000
|
|
||||||
MountParentDir = %s/mnt
|
|
||||||
DefaultCipher = aes-cbc-essiv:sha256
|
DefaultCipher = aes-cbc-essiv:sha256
|
||||||
|
[Locations]
|
||||||
|
NameDatabase = %s/cryptobox_names.db
|
||||||
|
MountParentDir = %s
|
||||||
|
TemplateDir = ../templates
|
||||||
|
LangDir = ../lang
|
||||||
|
DocDir = ../doc/html
|
||||||
[Log]
|
[Log]
|
||||||
Level = debug
|
Level = debug
|
||||||
Destination = file
|
Destination = file
|
||||||
|
@ -82,29 +83,28 @@ CryptoBoxRootActions = CryptoBoxRootActions
|
||||||
def testConfigInit(self):
|
def testConfigInit(self):
|
||||||
'''Check various branches of config file loading'''
|
'''Check various branches of config file loading'''
|
||||||
import os
|
import os
|
||||||
self.assertRaises("ConfigError", self.CryptoBox.CryptoBoxProps,"/invalid/path/to/config/file")
|
self.assertRaises(CBConfigUnavailableError, self.CryptoBox.CryptoBoxProps,"/invalid/path/to/config/file")
|
||||||
self.assertRaises("ConfigError", self.CryptoBox.CryptoBoxProps,"/etc/shadow")
|
self.assertRaises(CBConfigUnavailableError, self.CryptoBox.CryptoBoxProps,"/etc/shadow")
|
||||||
for a in self.CryptoBox.CONF_LOCATIONS:
|
for a in self.CryptoBox.CONF_LOCATIONS:
|
||||||
if os.path.exists(a): self.CryptoBox.CryptoBoxProps()
|
if os.path.exists(a): self.CryptoBox.CryptoBoxProps()
|
||||||
else: self.assertRaises("ConfigError", self.CryptoBox.CryptoBoxProps)
|
else: self.assertRaises(CBConfigUnavailableError, self.CryptoBox.CryptoBoxProps)
|
||||||
self.CryptoBox.CryptoBoxProps(self.filenames["configFileOK"])
|
self.CryptoBox.CryptoBoxProps(self.filenames["configFileOK"])
|
||||||
self.assertRaises("ConfigError", self.CryptoBox.CryptoBoxProps,[])
|
self.assertRaises(CBConfigUnavailableError, self.CryptoBox.CryptoBoxProps,[])
|
||||||
|
|
||||||
def testBrokenConfigs(self):
|
def testBrokenConfigs(self):
|
||||||
"""Check various broken configurations"""
|
"""Check various broken configurations"""
|
||||||
self.writeConfig("NameDatabase", "#out", filename=self.filenames["configFileBroken"])
|
self.writeConfig("NameDatabase", "#out", filename=self.filenames["configFileBroken"])
|
||||||
self.assertRaises("ConfigError", self.CryptoBox.CryptoBoxProps,self.filenames["configFileBroken"])
|
self.assertRaises(CBConfigUndefinedError, self.CryptoBox.CryptoBoxProps,self.filenames["configFileBroken"])
|
||||||
self.writeConfig("Level", "#out", filename=self.filenames["configFileBroken"])
|
self.writeConfig("Level", "#out", filename=self.filenames["configFileBroken"])
|
||||||
self.assertRaises("ConfigError", self.CryptoBox.CryptoBoxProps,self.filenames["configFileBroken"])
|
self.assertRaises(CBConfigUndefinedError, self.CryptoBox.CryptoBoxProps,self.filenames["configFileBroken"])
|
||||||
self.writeConfig("Details", "#out", filename=self.filenames["configFileBroken"])
|
self.writeConfig("Details", "#out", filename=self.filenames["configFileBroken"])
|
||||||
self.assertRaises("ConfigError", self.CryptoBox.CryptoBoxProps,self.filenames["configFileBroken"])
|
self.assertRaises(CBConfigUndefinedError, self.CryptoBox.CryptoBoxProps,self.filenames["configFileBroken"])
|
||||||
self.writeConfig("super", "super=/bin/invalid/no", filename=self.filenames["configFileBroken"])
|
self.writeConfig("super", "super=/bin/invalid/no", filename=self.filenames["configFileBroken"])
|
||||||
self.assertRaises("ConfigError", self.CryptoBox.CryptoBoxProps,self.filenames["configFileBroken"])
|
self.assertRaises(CBEnvironmentError, self.CryptoBox.CryptoBoxProps,self.filenames["configFileBroken"])
|
||||||
self.writeConfig("CryptoBoxRootActions", "#not here", filename=self.filenames["configFileBroken"])
|
self.writeConfig("CryptoBoxRootActions", "#not here", filename=self.filenames["configFileBroken"])
|
||||||
self.assertRaises("ConfigError", self.CryptoBox.CryptoBoxProps,self.filenames["configFileBroken"])
|
self.assertRaises(CBConfigUndefinedError, self.CryptoBox.CryptoBoxProps,self.filenames["configFileBroken"])
|
||||||
self.writeConfig("CryptoBoxRootActions", "CryptoBoxRootActions = /bin/false", filename=self.filenames["configFileBroken"])
|
self.writeConfig("CryptoBoxRootActions", "CryptoBoxRootActions = /bin/false", filename=self.filenames["configFileBroken"])
|
||||||
self.assertRaises("ConfigError", self.CryptoBox.CryptoBoxProps,self.filenames["configFileBroken"])
|
self.assertRaises(CBEnvironmentError, self.CryptoBox.CryptoBoxProps,self.filenames["configFileBroken"])
|
||||||
# TODO: check details of different ConfigError-exceptions
|
|
||||||
|
|
||||||
|
|
||||||
def writeConfig(self, replace=None, newline=None, filename=None):
|
def writeConfig(self, replace=None, newline=None, filename=None):
|
||||||
|
|
Loading…
Reference in a new issue