Browse Source

added setup.py to use distutils for packaging

moved python modules to separate packages below src/
renamed "hook" to "event" to avoid confusion
master
lars 16 years ago
parent
commit
112979b3af
  1. 0
      CHANGELOG
  2. 8
      MANIFEST.in
  3. 0
      bin/CryptoBoxRootActions
  4. 173
      bin/CryptoBoxWebserver
  5. 110
      bin/CryptoBoxWebserver.py
  6. 2
      bin/cryptobox.conf
  7. 15
      bin/run_webserver.sh
  8. 116
      bin/test.complete.CryptoBox.py
  9. 3
      debian/control
  10. 12
      debian/cryptobox.default
  11. 72
      debian/cryptobox.init
  12. 2
      debian/postinst
  13. 5
      debian/rules
  14. 0
      event-scripts/README
  15. 0
      event-scripts/apache2_dav
  16. 0
      event-scripts/samba
  17. 4
      plugins/date/date.py
  18. 4
      plugins/disks/disks.py
  19. 4
      plugins/help/help.py
  20. 4
      plugins/language_selection/language_selection.py
  21. 4
      plugins/logs/logs.py
  22. 4
      plugins/network/network.py
  23. 26
      plugins/partition/partition.py
  24. 8
      plugins/plugin_manager/plugin_manager.py
  25. 4
      plugins/shutdown/shutdown.py
  26. 4
      plugins/system_preferences/system_preferences.py
  27. 4
      plugins/user_manager/user_manager.py
  28. 6
      plugins/volume_automount/volume_automount.py
  29. 6
      plugins/volume_chpasswd/volume_chpasswd.py
  30. 4
      plugins/volume_details/volume_details.py
  31. 6
      plugins/volume_format_fs/format_fs.py
  32. 6
      plugins/volume_format_fs/volume_format_fs.py
  33. 6
      plugins/volume_mount/volume_mount.py
  34. 12
      plugins/volume_props/volume_props.py
  35. 6
      plugins/volume_rename/volume_rename.py
  36. 59
      setup.py
  37. 1
      src/__init__.py
  38. 0
      src/core/__init__.py
  39. 49
      src/core/container.py
  40. 8
      src/core/exceptions.py
  41. 31
      src/core/main.py
  42. 48
      src/core/settings.py
  43. 0
      src/core/tools.py
  44. 0
      src/plugins/__init__.py
  45. 0
      src/plugins/base.py
  46. 0
      src/plugins/manage.py
  47. 0
      src/tests/__init__.py
  48. 2
      src/tests/cryptobox.py
  49. 0
      src/tests/cryptoboxtools.py
  50. 4
      src/tests/plugins.py
  51. 6
      src/tests/websites.py
  52. 0
      src/web/__init__.py
  53. 24
      src/web/dataset.py
  54. 16
      src/web/sites.py
  55. 4
      src/web/testclass.py

8
MANIFEST.in

@ -0,0 +1,8 @@
include README
graft www-data
#graft www-data/screenshots
graft templates
graft lang
graft plugins
prune commit.log
prune package.exclude

0
bin/CryptoBoxRootActions.py → bin/CryptoBoxRootActions

173
bin/CryptoBoxWebserver

@ -0,0 +1,173 @@
#!/usr/bin/python2.4
import os, sys
import cryptobox.web.sites
from cryptobox.core.exceptions import *
from optparse import OptionParser
try:
import cherrypy
except:
print "Could not import the cherrypy module! Try 'apt-get install python-cherrypy'."
sys.exit(1)
# TODO: change this for the release version
SERVER_ENVIRONMENT = "development"
class CryptoBoxWebserver:
'''this class starts the cherryp webserver and serves the single sites'''
def __init__(self, opts):
## check conffile
if not os.access(opts.conffile, os.R_OK) or not os.path.isfile(opts.conffile):
sys.stderr.write("Error: could not read configuration file (%s)\n" % opts.conffile)
sys.exit(1)
## store the absolute path as we will chdir later (for daemons)
self.conffile = os.path.realpath(opts.conffile)
## initialize site class
try:
cherrypy.root = cryptobox.web.sites.WebInterfaceSites(self.conffile)
except (CBConfigError,CBEnvironmentError), errMsg:
sys.stderr.write("Error: the CryptoBox is misconfigured - please fix it!\n")
sys.stderr.write("%s\n" % str(errMsg))
sys.exit(1)
#expose static content:
#I currently have no idea how to cleanly extract the stylesheet path from
#the config object without an extra cryptobox.core.main.CryptoBoxProps instance.
#perhaps put config handling into a separate class in CryptoBox.py?
#
# the following manual mapping is necessary, as we may not use relative
# paths in the config file
cherrypy.config.update({
"global": {
"server.socket_port" : int(opts.port),
"server.socket_host" : opts.host,
"server.log_to_screen" : not opts.background and opts.verbose,
"server.log_tracebacks" : opts.verbose,
"server.environment": SERVER_ENVIRONMENT,
"server.log_file" : opts.logfile },
"/cryptobox-misc": {
"staticFilter.on" : True,
"staticFilter.dir": os.path.realpath(opts.datadir)}
})
def start(self):
cherrypy.server.start()
def fork_to_background():
## this is just copy'n'pasted from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
## check the original for exhaustive comments
try:
pid = os.fork()
except OSError, errMsg:
sys.stderr.write("Error: failed to fork cryptobox daemon process!\n")
sys.stderr.write("%s\n" % errMsg)
sys.exit(1)
if pid == 0: # the first child
os.setsid()
try:
pid = os.fork()
except OSError, errMsg:
sys.stderr.write("Error: failed to fork second cryptobox daemon process!\n")
sys.stderr.write("%s\n" % errMsg)
sys.exit(1)
if pid == 0: # the second child
## we do not change the directory - otherwise there seems to be a race condition with the python interpreter loading this script file
#os.chdir(os.path.sep)
os.umask(0)
else:
os._exit(0)
else:
os._exit(0)
def close_open_files():
"""this is only necessary if we want to go into background"""
import resource # Resource usage information.
maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
if (maxfd == resource.RLIM_INFINITY):
maxfd = 1024
for fd in range(0, maxfd):
try:
os.close(fd)
except OSError: # ERROR, fd wasn't open to begin with (ignored)
pass
os.open(os.devnull, os.O_RDWR) # standard input (0)
os.dup2(0, 1) # standard output (1)
os.dup2(0, 2) # standard error (2)
def write_pid_file(pid_file):
try:
pidf = open(pid_file,"w")
pidf.write(str(os.getpid()))
pidf.close()
except (IOError, OSError), errMsg:
sys.stderr.write("Warning: failed to write pid file (%s): %s\n" % (pid_file, errMsg))
## it is just a warning - no need to break
def parseOptions():
version = "%prog" + cryptobox.core.main.VERSION
parser = OptionParser(version=version)
parser.set_defaults(conffile="/etc/cryptobox/webserver.conf",
pidfile="/var/run/cryptobox/webserver.pid",
background=False,
datadir="/usr/share/cryptobox/html",
logfile="/var/log/cryptobox/webserver.log",
port="8080",
host="",
verbose=True)
parser.add_option("-c", "--config", dest="conffile",
help="read configuration from FILE", metavar="FILE")
parser.add_option("","--pidfile", dest="pidfile",
help="write process id to FILE", metavar="FILE")
parser.add_option("-B","", dest="background", action="store_true",
help="run webserver in background (as daemon)")
parser.add_option("-q","", dest="verbose", action="store_false",
help="output only errors")
parser.add_option("","--datadir", dest="datadir", metavar="DIR",
help="set data directory to DIR")
parser.add_option("-p","--port", dest="port", metavar="PORT",
help="listen on PORT")
parser.add_option("-l","--logfile", dest="logfile", metavar="FILE",
help="write webserver log to FILE")
parser.add_option("","--host", dest="host", metavar="HOST",
help="attach to HOST")
(options, args) = parser.parse_args()
## we do not expect any remaining arguments
if len(args) != 0:
parser.error("unknown argument: %s" % str(args[0]))
if not os.path.isdir(options.datadir) or not os.access(options.datadir,os.X_OK):
parser.error("could not access the data directory (%s)" % options.datadir)
try:
if (int(options.port) < 0) or (int(options.port) > 65535):
parser.error("invalid port number: %s" % str(options.port))
except ValueError:
parser.error("invalid port specified (%s) - it must be a number" % (options.port))
return options
if __name__ == "__main__":
## process arguments
options = parseOptions()
## initialize the webserver class (before forking to get some error messages)
cbw = CryptoBoxWebserver(options)
## run the webserver as a daemon process
if options.background: fork_to_background()
## write pid file
write_pid_file(options.pidfile)
## close open files to allow background execution
if options.background: close_open_files()
## start the webserver
try:
cbw.start()
except CBError, errMsg:
sys.stderr.write("Failed to start the CryptoBox webserver!\n")
sys.stderr.write("%s\n" % str(errMsg))
sys.stderr.write("Check the log file for details.\n")
sys.exit(1)
sys.exit(0)

110
bin/CryptoBoxWebserver.py

@ -1,110 +0,0 @@
#!/usr/bin/python2.4
import os
import WebInterfaceSites
from CryptoBoxExceptions import *
import sys
try:
import cherrypy
except:
print "Could not import the cherrypy module! Try 'apt-get install python-cherrypy'."
sys.exit(1)
## TODO: it should be possible to override this via commandline arguments
PID_FILE = '/var/run/cryptobox/webserver.pid'
class CryptoBoxWebserver:
'''this class starts the cherryp webserver and serves the single sites'''
def __init__(self):
try:
cherrypy.root = WebInterfaceSites.WebInterfaceSites()
except (CBConfigError,CBEnvironmentError), errMsg:
sys.stderr.write("The CryptoBox is misconfigured - please fix it!\n")
sys.stderr.write("%s\n" % str(errMsg))
sys.exit(1)
#expose static content:
#I currently have no idea how to cleanly extract the stylesheet path from
#the config object without an extra CryptoBox.CryptoBoxProps instance.
#perhaps put config handling into a separate class in CryptoBox.py?
#
# the following manual mapping is necessary, as we may not use relative
# paths in the config file
cherrypy.config.configMap.update({
"/cryptobox-misc": {
"staticFilter.on" : True,
"staticFilter.dir": os.path.abspath("/usr/share/cryptobox/html" )}
})
def start(self):
# just use this config, when we're started directly
cherrypy.config.update(file = "/etc/cryptobox/cryptoboxwebserver.conf")
cherrypy.server.start()
def fork_to_background():
## this is just copy'n'pasted from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
## check the original for exhaustive comments
try:
pid = os.fork()
except OSError, errMsg:
sys.stderr.write("Failed to fork cryptobox daemon process!\n")
sys.stderr.write("%s\n" % errMsg)
sys.exit(1)
if pid == 0: # the first child
os.setsid()
try:
pid = os.fork()
except OSError, errMsg:
sys.stderr.write("Failed to fork second cryptobox daemon process!\n")
sys.stderr.write("%s\n" % errMsg)
sys.exit(1)
if pid == 0: # the second child
os.chdir(os.path.sep)
os.umask(0)
else:
os._exit(0)
else:
os._exit(0)
import resource # Resource usage information.
maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
if (maxfd == resource.RLIM_INFINITY):
maxfd = 1024
for fd in range(0, maxfd):
try:
os.close(fd)
except OSError: # ERROR, fd wasn't open to begin with (ignored)
pass
os.open(os.devnull, os.O_RDWR) # standard input (0)
os.dup2(0, 1) # standard output (1)
os.dup2(0, 2) # standard error (2)
def write_pid_file(pid_file):
try:
pidf = open(pid_file,"w")
pidf.write(str(os.getpid()))
pidf.close()
except (IOError, OSError), errMsg:
sys.stderr.write("Failed to write pid file (%s): %s\n" % (pid_file, errMsg))
## it is just a warning - no need to break
if __name__ == "__main__":
## TODO: add some argument checking: configFile, daemonMode, ...
cbw = CryptoBoxWebserver()
## run the webserver as a daemon process
fork_to_background()
## write pid file
write_pid_file(PID_FILE)
try:
cbw.start()
except Exceptions, errMsg:
sys.stderr.write("Failed to start the CryptoBox webserver!\n")
sys.stderr.write("%s\n" % str(errMsg))
sys.stderr.write("Check the log file for details.\n")
sys.exit(1)
sys.exit(0)

2
bin/cryptobox.conf

@ -38,7 +38,7 @@ TemplateDir = ../templates
LangDir = ../lang
# path to documentation files
#DocDir = /usr/share/doc/cryptobox/html
#DocDir = /usr/share/doc/cryptobox/www-data
DocDir = ../doc/html
# path to the plugin directory

15
bin/run_webserver.sh

@ -0,0 +1,15 @@
#!/bin/sh
#
# example start script to run a local cryptobox webserver
#
# we set some en
#
BIN_DIR=$(dirname "$0")
## add the local python directory to the search path
export PYTHONPATH="$BIN_DIR/../src"
## run the webserver
"$BIN_DIR/CryptoBoxWebserver" --config="$BIN_DIR/cryptobox.conf" --pidfile=/tmp/cryptoboxwebserver.pid --logfile=/tmp/cryptoboxwebser.log --port=8080 --datadir="$BIN_DIR/../www-data" "$@"

116
bin/test.complete.CryptoBox.py

@ -1,116 +0,0 @@
#!/usr/bin/env python2.4
"""
BEWARE: this script may overwrite the data of one of your loop devices. You
should restrict the AllowedDevices directive in cryptobox.conf to exclude
your precious black devices from being used by this script.
the following script runs a number of tests for different parts
"""
from CryptoBox import CryptoBoxProps
from CryptoBoxContainer import CryptoBoxContainer
import sys
def main():
cb = CryptoBoxProps()
print "Confguration:"
print "\tConfig file:\t\t%s" % (cb.prefs.prefs.filename, )
print "\tAllowed devices:\t%s" % (cb.prefs["Main"]["AllowedDevices"], )
"""for e in cb.getContainerList(filterType=CryptoBoxContainer.Types["luks"]):"""
for e in cb.getContainerList():
print "\t\t%d\t\t%s - %s - %d" % (cb.getContainerList().index(e), e.getDevice(), e.getName(), e.getType())
if not cb.getContainerList() or len(cb.getContainerList()) < 1:
print "no loop devices found for testing"
sys.exit(1)
if len(cb.getContainerList()) > 1:
print "I found more than one available loop device - I will stop now to avoid risking data loss."
print "Please change the 'AllowedDevices' setting in 'cryptobox.conf' to reduce the number of allowed devices to only one."
sys.exit(1)
testElement = cb.getContainerList()[0]
print "\nRunning some tests now ..."
if not plain_tests(testElement):
print "some previous tests failed - we should stop now"
sys.exit(1)
luks_tests(testElement)
" ***************** some functions ******************** "
def luks_tests(e):
# umount if necessary
try:
e.umount()
except "MountError":
pass
e.create(e.Types["luks"], "alt")
print "\tluks create:\tok"
e.changePassword("alt","neu")
print "\tluks changepw:\tok"
e.setName("lalla")
print "\tluks setName:\tok"
try:
e.mount("neu")
except "MountError":
pass
if e.isMounted(): print "\tluks mount:\tok"
else: print "\tluks mount:\tfailed"
print "\tCapacity (size, free, used) [MB]:\t%s" % (e.getCapacity(), )
try:
e.umount()
except "MountError":
pass
if e.isMounted(): print "\tluks umount:\tfailed"
else: print "\tluks umount:\tok"
if e.isMounted(): return False
else: return True
def plain_tests(e):
# umount if necessary
try:
e.umount()
except "MountError":
pass
e.create(e.Types["plain"])
print "\tplain create:\tok"
e.setName("plain-lili")
print "\tplain setName:\tok"
try:
e.mount()
except "MountError":
pass
if e.isMounted(): print "\tplain mount:\tok"
else: print "\tplain mount:\tfailed"
print "\tCapacity (size, free, used) [MB]:\t%s" % (e.getCapacity(), )
try:
e.umount()
except "MountError":
pass
if e.isMounted(): print "\tplain umount:\tfailed"
else: print "\tplain umount:\tok"
if e.isMounted(): return False
else: return True
# ************ main ****************
main()

3
debian/control vendored

@ -2,7 +2,8 @@ Source: cryptobox
Section: admin
Priority: extra
Maintainer: Lars Kruse <devel@sumpfralle.de>
Build-Depends: debhelper (>= 5.0.37.2), dpatch, python-all-dev (>= 2.4)
Build-Depends: debhelper (>= 5.0.37.2), dpatch, python-all-dev (>= 2.4), python-central (>= 0.5.6)
XS-Python-Version: 2.4
Standards-Version: 3.7.2
Package: cryptobox

12
debian/cryptobox.default vendored

@ -7,5 +7,15 @@
# set to "0" to enable the startup of the cryptobox - otherwise "1"
NO_START=1
# the use that should execute the cryptobox
# the user that should execute the cryptobox
RUNAS=cryptobox
# listening port
PORT=8080
# log file of the webserver
LOGFILE=/var/log/cryptobox/webserver.log
# some more server options (rarely necessary)
#SERVER_OPTS="--host localhost --datadir=/usr/share/cryptobox/html"

72
debian/cryptobox.init vendored

@ -18,35 +18,27 @@
# read the default setting file, if it exists
[ -e /etc/default/cryptobox ] && source /etc/default/cryptobox
[ -r /etc/default/cryptobox ] && source /etc/default/cryptobox
# startup switch defaults to zero (enabled)
# set default values (if not defined in /etc/default/cryptobox)
NO_START=${NO_START:-0}
RUNAS=${RUNAS:-cryptobox}
PORT=${PORT:-8080}
HOST=${HOST:-}
LOGFILE=${LOGFILE:-/var/log/cryptobox/webserver.log}
SERVER_OPTS=${SERVER_OPTS:-}
CONF_FILE=/etc/cryptobox/cryptobox.conf
if [ "$NO_START" = "1" ]
then [ $# -eq 0 ] && exit 0
[ "$1" = "status" ] && exit 1
[ "$1" = "stop" ] && exit 0
echo "CryptoBox is disabled by default (check /etc/default/cryptobox)"
exit 0
fi
CBXSERVER=CryptoBoxWebserver.py
if test -e "./$CBXSERVER"
then CBXPATH=$(pwd)
else CBXPATH=/usr/lib/cryptobox
fi
# quit if NO_START is 1 (see /etc/default/cryptobox)
[ "$NO_START" = "1" ] && exit 0
DAEMON=/usr/bin/CryptoBoxWebserver
PIDFILE=/var/run/cryptobox/webserver.pid
DAEMON=/usr/bin/python2.4
DAEMON_OPTS=$CBXPATH/$CBXSERVER
NAME=cryptoboxd
DESC="CryptoBox Daemon (webinterface)"
OPTIONS="-B --pidfile=$PIDFILE --config=$CONF_FILE $SERVER_OPTS"
# check if the package is installed
test -e "$CBXPATH/$CBXSERVER" || exit 0
test -e "$DAEMON" || exit 0
# include some useful functions to unify our output format
. /lib/lsb/init-functions
@ -57,24 +49,28 @@ case "$1" in
# TODO: create certificate
# TODO: run stunnel
# the lines above should go into the live-cd scripts
test -e "$PIDFILE" && log_warning_msg "CryptoBox seems to running already (pid file exists) - we will try to start it anyway ..."
log_daemon_msg "Starting cryptobox webserver" "$DESC"
## create the directory of the pid file if necessary
PIDDIR=$(dirname "$PIDFILE")
if [ -d "$PIDDIR" ]
then mkdir -p "$PIDDIR"
chown $RUNAS:root "$PIDDIR"
chmod 755 "$PIDDIR"
fi
log_daemon_msg "Starting $DESC"
if start-stop-daemon \
--chdir "$CBXPATH" --chuid "$RUNAS" --quiet --start \
-oknodo --user "$RUNAS" --pidfile "$PIDFILE" \
--exec "$DAEMON" -- $DAEMON_OPTS
--chuid $RUNAS: --quiet --start \
--oknodo --user $RUNAS --pidfile "$PIDFILE" \
--exec /usr/bin/python --startas "$DAEMON" -- $OPTIONS
then log_end_msg 0
else log_end_msg 1
exit 1
fi
;;
stop )
if test ! -e "$PIDFILE"
then log_warning_msg "CryptoBox is not running (no pid file found)"
exit 0
fi
log_daemon_msg "Stopping cryptobox webserver" "$DESC"
if start-stop-daemon --quiet --stop --pidfile "$PIDFILE"
if start-stop-daemon --oknodo --quiet --stop \
--pidfile "$PIDFILE" \
--user "$RUNAS"
then rm "$PIDFILE"
log_end_msg 0
else log_end_msg 1
@ -86,8 +82,22 @@ case "$1" in
sleep 1
"$0" start
;;
status )
echo -n "$DESC "
if start-stop-daemon --stop --signal 0 --quiet \
--pidfile "$PIDFILE" -user "$RUNAS"
then echo "running"
exit 0
else if [ -e "$PIDFILE" ]
then echo "failed"
exit 1
else echo "not running"
exit 0
fi
fi
;;
* )
echo "Usage: $0 {start|stop|restart|reload|force-reload}" >&2
echo "Usage: $0 {start|stop|restart|force-reload|status}" >&2
exit 1
;;
esac

2
debian/postinst vendored

@ -35,7 +35,7 @@ create_add_super_permission()
## do nothing, if there is already a CryptoBox line
grep -q "CRYPTOBOX_MARKER" "$SUPER_FILE" && return 0
echo >>"$SUPER_FILE" "## CRYPTOBOX_MARKER - please do not remove!"
echo >>"$SUPER_FILE" "CryptoBoxRootActions /usr/lib/cryptobox/CryptoBoxRootActions.py $CRYPTOBOX_USER"
echo >>"$SUPER_FILE" "CryptoBoxRootActions /usr/bin/CryptoBoxRootActions $CRYPTOBOX_USER"
}
create_pid_dir()

5
debian/rules vendored

@ -51,9 +51,10 @@ install: build
dh_testroot
dh_clean -k
dh_installdirs
$(MAKE) install PREFIX=$(DEB_BUILD_DIR)/usr
dh_pycentral
python setup.py install --root=debian/cryptobox
install -c -m 644 conf-examples/cryptobox.conf-dist $(DEB_BUILD_DIR)/etc/cryptobox/cryptobox.conf
install -c -m 644 conf-examples/cryptoboxwebserver.conf-dist $(DEB_BUILD_DIR)/etc/cryptobox/cryptoboxwebserver.conf
install -c -m 644 conf-examples/cryptoboxwebserver.conf-dist $(DEB_BUILD_DIR)/etc/cryptobox/webserver.conf
# Build architecture-independent files here.

0
hook-scripts/README → event-scripts/README

0
hook-scripts/apache2_dav → event-scripts/apache2_dav

0
hook-scripts/samba → event-scripts/samba

4
plugins/date/date.py

@ -1,7 +1,7 @@
import CryptoBoxPlugin
import cryptobox.plugins.base
class date(CryptoBoxPlugin.CryptoBoxPlugin):
class date(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "system" ]
pluginVisibility = [ "preferences" ]

4
plugins/disks/disks.py

@ -1,6 +1,6 @@
import CryptoBoxPlugin
import cryptobox.plugins.base
class disks(CryptoBoxPlugin.CryptoBoxPlugin):
class disks(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "system" ]
pluginVisibility = [ "menu" ]

4
plugins/help/help.py

@ -1,6 +1,6 @@
import CryptoBoxPlugin
import cryptobox.plugins.base
class help(CryptoBoxPlugin.CryptoBoxPlugin):
class help(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "system" ]
pluginVisibility = [ "menu" ]

4
plugins/language_selection/language_selection.py

@ -1,7 +1,7 @@
import CryptoBoxPlugin
import cryptobox.plugins.base
class language_selection(CryptoBoxPlugin.CryptoBoxPlugin):
class language_selection(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "system" ]
pluginVisibility = [ "menu", "preferences" ]

4
plugins/logs/logs.py

@ -1,7 +1,7 @@
import CryptoBoxPlugin
import cryptobox.plugins.base
import os
class logs(CryptoBoxPlugin.CryptoBoxPlugin):
class logs(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "system" ]
pluginVisibility = [ "preferences" ]

4
plugins/network/network.py

@ -1,13 +1,13 @@
import subprocess
import os
import CryptoBoxPlugin
import cryptobox.plugins.base
## specify (in seconds), how long we should wait before redirecting and ip change
REDIRECT_DELAY=20
CHANGE_IP_DELAY=1
class network(CryptoBoxPlugin.CryptoBoxPlugin):
class network(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "system" ]
pluginVisibility = [ "preferences" ]

26
plugins/partition/partition.py

@ -1,10 +1,10 @@
import subprocess
import os
import logging
import CryptoBoxTools
import CryptoBoxPlugin
import cryptobox.core.tools as cbxTools
import cryptobox.plugins.base
class partition(CryptoBoxPlugin.CryptoBoxPlugin):
class partition(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "system" ]
pluginVisibility = [ "preferences" ]
@ -80,7 +80,7 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
return False
if not self.cbox.isDeviceAllowed(device):
return False
if not device in CryptoBoxTools.getParentBlockDevices():
if not device in cbxTools.getParentBlockDevices():
return False
return True
@ -96,14 +96,13 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
def __actionSelectDevice(self, args):
import CryptoBoxTools
block_devices = [e
for e in CryptoBoxTools.getParentBlockDevices()
for e in cbxTools.getParentBlockDevices()
if self.cbox.isDeviceAllowed(e)]
counter = 0
for a in block_devices:
self.hdf[self.hdf_prefix + "BlockDevices.%d.name" % counter] = a
self.hdf[self.hdf_prefix + "BlockDevices.%d.size" % counter] = CryptoBoxTools.getBlockDeviceSizeHumanly(a)
self.hdf[self.hdf_prefix + "BlockDevices.%d.size" % counter] = cbxTools.getBlockDeviceSizeHumanly(a)
self.cbox.log.debug("found a suitable block device: %s" % a)
counter += 1
if self.withConfigPartition:
@ -143,7 +142,7 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
parts = self.__getPartitionsFromArgs(args)
if parts:
self.__setPartitionData(parts)
if CryptoBoxTools.isPartOfBlockDevice(self.device, self.cbox.prefs.getActivePartition()):
if cbxTools.isPartOfBlockDevice(self.device, self.cbox.prefs.getActivePartition()):
self.cbox.prefs.umountPartition()
if not self.__runFDisk(parts):
self.hdf["Data.Warning"] = "Plugins.partition.PartitioningFailed"
@ -189,7 +188,7 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
## we do not have to take special care for a possible config partition
parts = [ { "size": self.deviceSize, "type": "windows" } ]
## umount partition if necessary
if CryptoBoxTools.isPartOfBlockDevice(self.device, self.cbox.prefs.getActivePartition()):
if cbxTools.isPartOfBlockDevice(self.device, self.cbox.prefs.getActivePartition()):
self.cbox.prefs.umountPartition()
## partition it
if not self.__runFDisk(parts):
@ -229,10 +228,10 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
for t in self.PartTypes.keys():
self.hdf[self.hdf_prefix + "Types.%s" % t] = t
## store the currently existing partitions of the choosen block device
current_containers = [ e for e in self.cbox.getContainerList() if CryptoBoxTools.isPartOfBlockDevice(self.device, e.getDevice()) ]
current_containers = [ e for e in self.cbox.getContainerList() if cbxTools.isPartOfBlockDevice(self.device, e.getDevice()) ]
for (index, t) in enumerate(current_containers):
self.hdf[self.hdf_prefix + "ExistingContainers.%d.name" % index] = t.getName()
self.hdf[self.hdf_prefix + "ExistingContainers.%d.size" % index] = CryptoBoxTools.getBlockDeviceSizeHumanly(t.getDevice())
self.hdf[self.hdf_prefix + "ExistingContainers.%d.size" % index] = cbxTools.getBlockDeviceSizeHumanly(t.getDevice())
def __getPartitionsFromArgs(self, args):
@ -264,8 +263,7 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
def __getAvailableDeviceSize(self, device):
"""calculate the available size (MB) of the device
also consider a (possible) configuration partition"""
import CryptoBoxTools
deviceSize = CryptoBoxTools.getBlockDeviceSize(device)
deviceSize = cbxTools.getBlockDeviceSize(device)
if deviceSize < 0: return 0
if self.withConfigPartition:
deviceSize -= self.ConfigPartition["size"]
@ -279,7 +277,7 @@ class partition(CryptoBoxPlugin.CryptoBoxPlugin):
## we need a partition, if there is no active one
if not active: return True
## check if the active one is part of the current device
return CryptoBoxTools.isPartOfBlockDevice(self.device, active)
return cbxTools.isPartOfBlockDevice(self.device, active)
return False

8
plugins/plugin_manager/plugin_manager.py

@ -1,8 +1,8 @@
import CryptoBoxPlugin
import Plugins
import cryptobox.plugins.base
import cryptobox.plugins.manage
class plugin_manager(CryptoBoxPlugin.CryptoBoxPlugin):
class plugin_manager(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "system" ]
pluginVisibility = [ "preferences" ]
@ -14,7 +14,7 @@ class plugin_manager(CryptoBoxPlugin.CryptoBoxPlugin):
if plugin_name:
## check for invalid characters
if re.search(u'\W', plugin_name): return "plugin_list"
pluginList = Plugins.PluginManager(self.cbox, self.cbox.prefs["Locations"]["PluginDir"])
pluginList = cryptobox.plugins.manage.PluginManager(self.cbox, self.cbox.prefs["Locations"]["PluginDir"])
plugin = pluginList.getPlugin(plugin_name)
if not plugin: return "plugin_list"
## take only plugins, that are of the same type as the choosen one

4
plugins/shutdown/shutdown.py

@ -1,8 +1,8 @@
import CryptoBoxPlugin
import cryptobox.plugins.base
REDIRECT_DELAY = 180
class shutdown(CryptoBoxPlugin.CryptoBoxPlugin):
class shutdown(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "system" ]
pluginVisibility = [ "preferences", "menu" ]

4
plugins/system_preferences/system_preferences.py

@ -1,6 +1,6 @@
import CryptoBoxPlugin
import cryptobox.plugins.base
class system_preferences(CryptoBoxPlugin.CryptoBoxPlugin):
class system_preferences(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "system" ]
pluginVisibility = [ "menu" ]

4
plugins/user_manager/user_manager.py

@ -1,8 +1,8 @@
import CryptoBoxPlugin
import cryptobox.plugins.base
RESERVED_USERS = [ "admin" ]
class user_manager(CryptoBoxPlugin.CryptoBoxPlugin):
class user_manager(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "system" ]
pluginVisibility = [ "preferences" ]

6
plugins/volume_automount/volume_automount.py

@ -1,8 +1,8 @@
import CryptoBoxPlugin
from CryptoBoxExceptions import *
import cryptobox.plugins.base
from cryptobox.core.exceptions import *
class volume_automount(CryptoBoxPlugin.CryptoBoxPlugin):
class volume_automount(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "volume" ]
pluginVisibility = [ "properties" ]

6
plugins/volume_chpasswd/volume_chpasswd.py

@ -1,8 +1,8 @@
import CryptoBoxPlugin
from CryptoBoxExceptions import *
import cryptobox.plugins.base
from cryptobox.core.exceptions import *
class volume_chpasswd(CryptoBoxPlugin.CryptoBoxPlugin):
class volume_chpasswd(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "volume" ]
pluginVisibility = [ "properties" ]

4
plugins/volume_details/volume_details.py

@ -1,7 +1,7 @@
import CryptoBoxPlugin
import cryptobox.plugins.base
class volume_details(CryptoBoxPlugin.CryptoBoxPlugin):
class volume_details(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "volume" ]
pluginVisibility = [ "volume" ]

6
plugins/volume_format_fs/format_fs.py

@ -1,7 +1,7 @@
import CryptoBoxPlugin
from CryptoBoxExceptions import *
import cryptobox.plugins.base
from cryptobox.core.exceptions import *
class format_fs(CryptoBoxPlugin.CryptoBoxPlugin):
class format_fs(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "volume" ]
pluginVisibility = [ "volume" ]

6
plugins/volume_format_fs/volume_format_fs.py

@ -1,7 +1,7 @@
import CryptoBoxPlugin
from CryptoBoxExceptions import *
import cryptobox.plugins.base
from cryptobox.core.exceptions import *
class volume_format_fs(CryptoBoxPlugin.CryptoBoxPlugin):
class volume_format_fs(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "volume" ]
pluginVisibility = [ "volume" ]

6
plugins/volume_mount/volume_mount.py

@ -1,8 +1,8 @@
import CryptoBoxPlugin
from CryptoBoxExceptions import *
import cryptobox.plugins.base
from cryptobox.core.exceptions import *
class volume_mount(CryptoBoxPlugin.CryptoBoxPlugin):
class volume_mount(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "volume" ]
pluginVisibility = [ "volume" ]

12
plugins/volume_props/volume_props.py

@ -1,9 +1,9 @@
import CryptoBoxPlugin
import Plugins
from CryptoBoxExceptions import *
import cryptobox.plugins.base
import cryptobox.plugins.manage
from cryptobox.core.exceptions import *
class volume_props(CryptoBoxPlugin.CryptoBoxPlugin):
class volume_props(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "volume" ]
pluginVisibility = [ "volume" ]
@ -13,7 +13,7 @@ class volume_props(CryptoBoxPlugin.CryptoBoxPlugin):
def doAction(self, **args):
import os
self.props_plugins = [e for e in Plugins.PluginManager(self.cbox, self.cbox.prefs["Locations"]["PluginDir"]).getPlugins() if "properties" in e.getVisibility()]
self.props_plugins = [e for e in cryptobox.plugins.manage.PluginManager(self.cbox, self.cbox.prefs["Locations"]["PluginDir"]).getPlugins() if "properties" in e.getVisibility()]
## sort plugins by rank
self.props_plugins.sort(cmp = self.__cmpPluginsRank)
## set the name of the templates for every plugin
@ -42,7 +42,7 @@ class volume_props(CryptoBoxPlugin.CryptoBoxPlugin):
for p in self.props_plugins:
p.loadDataSet(hdf)
## call our parent's method
CryptoBoxPlugin.CryptoBoxPlugin.loadDataSet(self, hdf)
cryptobox.plugins.base.CryptoBoxPlugin.loadDataSet(self, hdf)
def __cmpPluginsRank(self, p1, p2):

6
plugins/volume_rename/volume_rename.py

@ -1,8 +1,8 @@
import CryptoBoxPlugin
from CryptoBoxExceptions import *
import cryptobox.plugins.base
from cryptobox.core.exceptions import *
class volume_rename(CryptoBoxPlugin.CryptoBoxPlugin):
class volume_rename(cryptobox.plugins.base.CryptoBoxPlugin):
pluginCapabilities = [ "volume" ]
pluginVisibility = [ "properties" ]

59
setup.py

@ -0,0 +1,59 @@
#!/usr/bin/env python
from distutils.core import setup
import distutils.sysconfig
import os
## define some strings (not patterns) to exclude specific files or directories
IGNORE_FILES = [ '.svn' ]
## define the data destination directory (below the python directory - we will fix this for debian in the rules file)
datadir = distutils.sysconfig.get_python_lib()
## remove installation prefix to get relative path
datadir = datadir.replace(distutils.sysconfig.get_config_var("prefix") + os.path.sep, '')
datadir = os.path.join(datadir, 'cryptobox','share')
def getdatafiles(dirs):
filelist = []
def listfiles(srcdir):
## add the files of this directory
result = [(os.path.join(datadir,srcdir), [ os.path.join(srcdir, f) for f in os.listdir(srcdir) if os.path.isfile(os.path.join(srcdir, f)) and not f in IGNORE_FILES ])]
## add the files in subdirectories
for d in os.listdir(os.path.join(srcdir)):
if os.path.isdir(os.path.join(srcdir,d)) and not d in IGNORE_FILES:
result.extend(listfiles(os.path.join(srcdir,d)))
return result
for d in dirs:
filelist.extend(listfiles(d))
return filelist
setup(
name = 'cryptobox',
version = '0.3.0',
description = 'webinterface for handling encrypted disks',
author = 'Lars Kruse',
author_email = 'devel@sumpfralle.de',
maintainer = 'Lars Kruse',
maintainer_email = 'devel@sumpfralle.de',
license = 'GPL',
url = 'http://cryptobox.org',
packages = [ 'cryptobox', 'cryptobox.core', 'cryptobox.web', 'cryptobox.plugins', 'cryptobox.tests' ],
data_files = getdatafiles(['templates','www-data','lang','plugins','event-scripts','conf-examples']) + [
(datadir, ['README']),
(datadir, ['CHANGELOG']),
(datadir, ['LICENSE'])],
package_dir = { 'cryptobox': 'src' },
scripts = [ 'bin/CryptoBoxWebserver', 'bin/CryptoBoxRootActions' ],
classifiers = [
'Development Status :: 2 - Beta',
'Environment :: Web Environment',
'Intended Audience :: End Users/Desktop',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: GNU General Public License (GPL)',
'Topic :: System :: Systems Administration',
'Operating System :: POSIX',
'Operating System :: Unix',
'Programming Language :: Python'],
)

1
src/__init__.py

@ -0,0 +1 @@
__all__ = ['core','web','plugins','tests']

0
src/core/__init__.py

49
bin/CryptoBoxContainer.py → src/core/container.py

@ -1,5 +1,3 @@
#!/usr/bin/env python2.4
## check python version
import sys
(ver_major, ver_minor, ver_sub, ver_desc, ver_subsub) = sys.version_info
@ -11,7 +9,7 @@ import subprocess
import os
import re
import logging
from CryptoBoxExceptions import *
from cryptobox.core.exceptions import *
"""exceptions:
CBVolumeIsActive
@ -24,14 +22,15 @@ from CryptoBoxExceptions import *
CBChangePasswordError
"""
class CryptoBoxContainer:
ContainerTypes = {
"unused":0,
"plain":1,
"luks":2,
"swap":3,
}
Types = {
"unused":0,
"plain":1,
"luks":2,
"swap":3}
class CryptoBoxContainer:
__fsTypes = {
"plain":["ext3", "ext2", "vfat", "reiser"],
@ -126,8 +125,8 @@ class CryptoBoxContainer:
the result is a value in megabyte
an error is indicated by "-1"
"""
import CryptoBoxTools
return CryptoBoxTools.getBlockDeviceSize(self.device)
import cryptobox.core.tools as cbxtools
return cbxtools.getBlockDeviceSize(self.device)
def resetObject(self):
@ -137,19 +136,19 @@ class CryptoBoxContainer:
self.type = self.__getTypeOfPartition()
self.name = self.__getNameOfContainer()
self.__setAttributes()
if self.type == self.Types["luks"]:
if self.type == ContainerTypes["luks"]:
self.mount = self.__mountLuks
self.umount = self.__umountLuks
elif self.type == self.Types["plain"]:
elif self.type == ContainerTypes["plain"]:
self.mount = self.__mountPlain
self.umount = self.__umountPlain
def create(self, type, password=None):
old_name = self.getName()
if type == self.Types["luks"]:
if type == ContainerTypes["luks"]:
self.__createLuks(password)
elif type == self.Types["plain"]:
elif type == ContainerTypes["plain"]:
self.__createPlain()
else:
raise CBInvalidType("invalid container type (%d) supplied" % (type, ))
@ -161,7 +160,7 @@ class CryptoBoxContainer:
def changePassword(self, oldpw, newpw):
if self.type != self.Types["luks"]:
if self.type != ContainerTypes["luks"]:
raise CBInvalidType("changing of password is possible only for luks containers")
if not oldpw:
raise CBInvalidPassword("no old password supplied for password change")
@ -247,7 +246,7 @@ class CryptoBoxContainer:
def __getUUID(self):
if self.__getTypeOfPartition() == self.Types["luks"]:
if self.__getTypeOfPartition() == ContainerTypes["luks"]:
guess = self.__getLuksUUID()
else:
guess = self.__getNonLuksUUID()
@ -302,14 +301,14 @@ class CryptoBoxContainer:
def __getTypeOfPartition(self):
"retrieve the type of the given partition (see CryptoBoxContainer.Types)"
if self.__isLuksPartition(): return self.Types["luks"]
"retrieve the type of the given partition (see cryptobox.core.container.ContainerTypes)"
if self.__isLuksPartition(): return ContainerTypes["luks"]
typeOfPartition = self.__getTypeIdOfPartition()
if typeOfPartition in self.__fsTypes["plain"]:
return self.Types["plain"]
return ContainerTypes["plain"]
if typeOfPartition in self.__fsTypes["swap"]:
return self.Types["swap"]
return self.Types["unused"]
return ContainerTypes["swap"]
return ContainerTypes["unused"]
def __getTypeIdOfPartition(self):
@ -645,8 +644,8 @@ class CryptoBoxContainer:
def __getEventArgs(self):
"""return an array of arguments for hook scripts handling pre/post-mount/umount
"""return an array of arguments for event scripts handling pre/post-mount/umount
events"""
typeText = [e for e in self.Types.keys() if self.Types[e] == self.getType()][0]
typeText = [e for e in ContainerTypes.keys() if ContainerTypes[e] == self.getType()][0]
return [self.getDevice(), self.getName(), typeText, self.__getMountPoint()]

8
bin/CryptoBoxExceptions.py → src/core/exceptions.py

@ -3,12 +3,12 @@ exceptions of the cryptobox package
"""
class CryptoBoxError(Exception):
class CBError(Exception):
"""base class for exceptions of the cryptobox"""
pass
class CBConfigError(CryptoBoxError):
class CBConfigError(CBError):
"""any kind of error related to the configuration of a cryptobox"""
pass
@ -57,7 +57,7 @@ class CBConfigInvalidValueError(CBConfigError):
return "invalid configuration setting [%s]->%s (%s): %s" % (self.section, self.name, self.value, self.reason)
class CBEnvironmentError(CryptoBoxError):
class CBEnvironmentError(CBError):
"""some part of the environment of the cryptobox is broken
e.g. the wrong version of a required program
"""
@ -69,7 +69,7 @@ class CBEnvironmentError(CryptoBoxError):
return "misconfiguration detected: %s" % self.desc
class CBContainerError(CryptoBoxError):
class CBContainerError(CBError):
"""any error raised while manipulating a cryptobox container"""
def __init__(self, desc):

31
bin/CryptoBox.py → src/core/main.py

@ -1,4 +1,3 @@
#!/usr/bin/env python2.4
'''
This is the web interface for a fileserver managing encrypted filesystems.
@ -14,14 +13,15 @@ if (ver_major < 2) or ((ver_major == 2) and (ver_minor < 4)):
sys.stderr.write("You need a python version >= 2.4\nCurrent version is:\n %s\n" % sys.version)
sys.exit(1)
import CryptoBoxContainer
from CryptoBoxExceptions import *
import cryptobox.core.container as cbxContainer
from cryptobox.core.exceptions import *
import re
import os
import CryptoBoxTools
import cryptobox.core.tools as cbxTools
import subprocess
VERSION = "0.3~1"
class CryptoBox:
'''this class rules them all!
@ -29,12 +29,11 @@ class CryptoBox:
put things like logging, conf and oter stuff in here,
that might be used by more classes, it will be passed on to them'''
VERSION = "0.3~1"
def __init__(self, config_file=None):
import CryptoBoxSettings
import cryptobox.core.settings as cbxSettings
self.log = self.__getStartupLogger()
self.prefs = CryptoBoxSettings.CryptoBoxSettings(config_file)
self.prefs = cbxSettings.CryptoBoxSettings(config_file)
self.__runTests()
@ -124,9 +123,9 @@ class CryptoBoxProps(CryptoBox):
def reReadContainerList(self):
self.log.debug("rereading container list")
self.containers = []
for device in CryptoBoxTools.getAvailablePartitions():
for device in cbxTools.getAvailablePartitions():
if self.isDeviceAllowed(device) and not self.isConfigPartition(device):
self.containers.append(CryptoBoxContainer.CryptoBoxContainer(device, self))
self.containers.append(cbxContainer.CryptoBoxContainer(device, self))
## sort by container name
self.containers.sort(cmp = lambda x,y: x.getName() < y.getName() and -1 or 1)
@ -187,7 +186,7 @@ class CryptoBoxProps(CryptoBox):
try:
result = self.containers[:]
if filterType != None:
if filterType in range(len(CryptoBoxContainer.Types)):
if filterType in range(len(cbxContainer.Types)):
return [e for e in self.containers if e.getType() == filterType]
else:
self.log.info("invalid filterType (%d)" % filterType)
@ -221,14 +220,14 @@ class CryptoBoxProps(CryptoBox):
def sendEventNotification(self, event, event_infos):
"""call all available scripts in the hook directory with some event information"""
hook_dir = self.prefs["Locations"]["HookDir"]
for fname in os.listdir(hook_dir):
real_fname = os.path.join(hook_dir, fname)
"""call all available scripts in the event directory with some event information"""