@ -3,6 +3,10 @@ import WebInterfaceDataset
import re
import Plugins
from CryptoBoxExceptions import *
import cherrypy
# TODO: for now the admin access is defined statically
authDict = { " test " : " tester " }
class WebInterfacePlugins :
@ -57,10 +61,48 @@ class WebInterfaceSites:
return False
## this is a function decorator to check authentication
## it has to be defined before any page definition requiring authentification
def __requestAuth ( self , authDict ) :
def check_credentials ( site ) :
def _inner_wrapper ( self , * args , * * kargs ) :
import base64
## define a "non-allowed" function
user , password = None , None
try :
resp = cherrypy . request . headers [ " Authorization " ] [ 6 : ] # ignore "Basic "
( user , password ) = base64 . b64decode ( resp ) . split ( " : " , 1 )
except KeyError :
## no "authorization" header was sent
pass
except TypeError :
## invalid base64 string
pass
except AttributeError :
## no cherrypy response header defined
pass
if user in authDict . keys ( ) :
if password == authDict [ user ] :
## ok: return the choosen page
self . cbox . log . info ( " access granted for: %s " % user )
return site ( self , * args , * * kargs )
else :
self . cbox . log . info ( " wrong password supplied for: %s " % user )
else :
self . cbox . log . info ( " unknown user: %s " % str ( user ) )
## wrong credentials: return "access denied"
cherrypy . response . headers [ " WWW-Authenticate " ] = ''' Basic realm= " Test-Arena " '''
cherrypy . response . status = 401
return self . __render ( " access_denied " )
return _inner_wrapper
return check_credentials
######################################################################
## put real sites down here and don't forget to expose them at the end
@cherrypy.expose
def status ( self , weblang = " " ) :
''' shows the current status of the box
'''
@ -79,6 +121,7 @@ class WebInterfaceSites:
return self . __render ( " show_status " )
@cherrypy.expose
def doc ( self , page = " " , weblang = " " ) :
''' prints the offline wikipage
'''
@ -96,18 +139,21 @@ class WebInterfaceSites:
return self . __render ( " show_doc " )
@cherrypy.expose
def system ( self , weblang = " " ) :
self . __resetDataset ( )
self . __setWebLang ( weblang )
return self . __render ( " form_system " )
@cherrypy.expose
def index ( self , weblang = " " ) :
self . __resetDataset ( )
self . __setWebLang ( weblang )
return self . __render ( " show_status " )
@cherrypy.expose
def show_volume ( self , device = " " , weblang = " " ) :
self . __resetDataset ( )
self . __setWebLang ( weblang )
@ -120,204 +166,75 @@ class WebInterfaceSites:
return self . __render ( " show_status " )
@cherrypy.expose
def show_volumes ( self , weblang = " " ) :
self . __resetDataset ( )
self . __setWebLang ( weblang )
return self . __render ( " show_volumes " )
def volume_name_set ( self , device = " " , volume_name = " " , weblang = " " ) :
self . __resetDataset ( )
self . __setWebLang ( weblang )
if self . __setDevice ( device ) :
volume_name = volume_name . strip ( )
if self . __checkVolumeName ( volume_name ) :
container = self . cbox . getContainer ( device )
try :
container . setName ( volume_name )
except CBContainerError , errMsg :
self . log . warn ( " failed to rename the volume ' %s ' to ' %s : %s ' " % ( device , volume_name , errMsg ) )
self . dataset [ " Data.Warning " ] = " SetVolumeNameFailed "
else :
self . log . info ( " successfully renamed volume ' %s ' to ' %s ' " % ( device , volume_name ) )
self . dataset . setCurrentDiskState ( device )
else :
self . dataset [ " Data.Warning " ] = " InvalidVolumeName "
return self . __render ( " show_volume " )
else :
if self . cbox . getContainerList ( ) :
return self . __render ( " show_volumes " )
else :
return self . __render ( " show_status " )
def mount_do ( self , device , crypto_password = None , weblang = " " ) :
self . __resetDataset ( )
self . __setWebLang ( weblang )
if self . __setDevice ( device ) :
container = self . cbox . getContainer ( device )
if container . isMounted ( ) :
self . dataset [ " Data.Warning " ] = " IsMounted "
self . log . warn ( " the device ( %s ) is already mounted " % device )
else :
def return_plugin_action ( self , plugin ) :
def handler ( self , * * args ) :
self . __resetDataset ( )
try :
self . __setWebLang ( args [ " weblang " ] )
del args [ " weblang " ]
except KeyError :
pass
## check the device argument of volume plugins
if " volume " in plugin . pluginCapabilities :
try :
if container . getType ( ) == container . Types [ " luks " ] :
## encrypted luks container
if not crypto_password :
self . dataset [ " Data.Warning " ] = " EmptyCryptoPassword "
self . log . warn ( " no password was supplied for mounting of device ' %s ' " % device )
return self . __render ( " show_volume " )
else :
container . mount ( crypto_password )
elif container . getType ( ) == container . Types [ " plain " ] :
## plain container
container . mount ( )
## initialize the dataset of the selected device if necessary
if self . __setDevice ( args [ " device " ] ) :
plugin . device = args [ " device " ]
self . dataset . setCurrentDiskState ( plugin . device )
else :
## mounting is not possible
self . dataset [ " Data.Warning " ] = " InvalidType "
self . log . warn ( " this type of container ( %s ) cannot be mounted - sorry! " % device )
except ( Exception , " MountError " ) :
self . dataset [ " Data.Warning " ] = " MountFailed "
self . log . warn ( " failed to mount the device ( %s ) " % device )
return self . __render ( " show_status " )
except KeyError :
return self . __render ( " show_status " )
else :
self . log . info ( " successfully mounted the container ( %s ) " % device )
self . dataset . setCurrentDiskState ( device )
else :
if self . cbox . getContainerList ( ) :
return self . __render ( " show_volumes " )
else :
return self . __render ( " show_status " )
return self . __render ( " show_volume " )
def volume_init_ask ( self , device , encryption = None , weblang = " " ) :
self . __resetDataset ( )
self . __setWebLang ( weblang )
if self . __setDevice ( device ) :
container = self . cbox . getContainer ( device )
if container . isMounted ( ) :
self . dataset [ " Data.Warning " ] = " VolumeMayNotBeMounted "
self . log . warn ( " initialization is not possible as long as the device ( %s ) is mounted " % device )
return self . __render ( " show_volume " )
else :
if encryption is None :
self . dataset [ " Data.Init.isCrypto " ] = 0
else :
self . dataset [ " Data.Init.isCrypto " ] = 1
return self . __render ( " form_init " )
else :
if self . cbox . getContainerList ( ) :
return self . __render ( " show_volumes " )
else :
return self . __render ( " show_status " )
def init_do ( self , device , confirm = " " , crypto_password = None , crypto_password2 = None , encryption = None , weblang = " " ) :
self . __resetDataset ( )
self . __setWebLang ( weblang )
if self . __setDevice ( device ) :
container = self . cbox . getContainer ( device )
## set 'Data.Init.isCrypto' - just in case, we have to show the same form again
if encryption is None :
self . dataset [ " Data.Init.isCrypto " ] = 0
else :
self . dataset [ " Data.Init.isCrypto " ] = 1
if container . isMounted ( ) :
self . dataset [ " Data.Warning " ] = " VolumeMayNotBeMounted "
self . log . warn ( " initialization is not possible as long as the device ( %s ) is mounted " % device )
return self . __render ( " form_init " )
## the parameter 'device' exists - we have to remove it
del args [ " device " ]
## call the plugin handler
nextTemplate = plugin . doAction ( * * args )
## for 'volume' plugins: reread the dataset of the current disk
## additionally: set the default template for plugins
if " volume " in plugin . pluginCapabilities :
self . dataset . setCurrentDiskState ( plugin . device )
if not nextTemplate : nextTemplate = " show_volume "
else :
if confirm != self . __getLanguageValue ( " Text.ConfirmInit " ) :
self . dataset [ " Data.Warning " ] = " InitNotConfirmed "
self . log . warn ( " the confirmation sentence for initialization of the device ' %s ' was wrong " % device )
return self . __render ( " form_init " )
try :
if not encryption is None :
if not crypto_password :
self . dataset [ " Data.Warning " ] = " EmptyCryptoPassword "
self . log . warn ( " no crypto password was supplied for initialization of device ' %s ' " % device )
return self . __render ( " form_init " )
if crypto_password != crypto_password2 :
self . dataset [ " Data.Warning " ] = " DifferentCryptoPasswords "
self . log . warn ( " the crypto password was not repeated correctly for initialization of device ' %s ' " % device )
return self . __render ( " form_init " )
container . create ( container . Types [ " luks " ] , crypto_password )
else :
container . create ( container . Types [ " plain " ] )
except CBContainerError , errMsg :
self . dataset [ " Data.Warning " ] = " CreateFailed "
self . log . warn ( " initialization of device ' %s ' failed " % device )
self . log . warn ( " reason: %s " % errMsg )
return self . __render ( " form_init " )
else :
self . log . info ( " successfully initialized device ' %s ' " % device )
# reread the dataset
self . dataset . setCurrentDiskState ( device )
return self . __render ( " show_volume " )
if not nextTemplate : nextTemplate = " form_system "
## save the currently active plugin name
self . dataset [ " Data.ActivePlugin " ] = plugin . getName ( )
return self . __render ( nextTemplate , plugin )
## apply authentication?
if plugin . requestAuth :
return lambda * * args : self . __requestAuth ( authDict ) ( handler ) ( self , * * args )
else :
if self . cbox . getContainerList ( ) :
return self . __render ( " show_volumes " )
else :
return self . __render ( " show_status " )
return lambda * * args : handler ( self , * * args )
## test authentication
@cherrypy.expose
@__requestAuth ( None , authDict )
def test ( self , weblang = " " ) :
import cherrypy
self . __resetDataset ( )
self . __setWebLang ( weblang )
return " test passed "
@cherrypy.expose
def test_stream ( self ) :
""" just for testing purposes - to check if the " stream_response " feature
actually works - for now ( September 02006 ) it does not seem to be ok """
import time
yield " <html><head><title>neu</title></head><body><p><ul> "
for a in range ( 10 ) :
yield " <li>yes: %d - %s </li> " % ( a , str ( time . time ( ) ) )
time . sleep ( 1 )
yield " </ul></p></html> "
def umount_do ( self , device , weblang = " " ) :
self . __resetDataset ( )
self . __setWebLang ( weblang )
if self . __setDevice ( device ) :
container = self . cbox . getContainer ( device )
if not container . isMounted ( ) :
self . dataset [ " Data.Warning " ] = " NotMounted "
self . log . warn ( " the device ( %s ) is currently not mounted " % device )
else :
try :
if container . getType ( ) == container . Types [ " luks " ] :
## encrypted luks container
container . umount ( )
elif container . getType ( ) == container . Types [ " plain " ] :
## plain container
container . umount ( )
else :
## umounting is not possible
self . dataset [ " Data.Warning " ] = " InvalidType "
self . log . warn ( " this type of container ( %s ) cannot be umounted - sorry! " % device )
except ( Exception , " UmountError " ) :
self . dataset [ " Data.Warning " ] = " UmountFailed "
self . log . warn ( " failed to unmount the device ( %s ) " % device )
else :
self . log . info ( " successfully unmounted the container ( %s ) " % device )
# reread the dataset
self . dataset . setCurrentDiskState ( device )
else :
if self . cbox . getContainerList ( ) :
return self . __render ( " show_volumes " )
else :
return self . __render ( " show_status " )
return self . __render ( " show_volume " )
def return_plugin_action ( self , plugin ) :
def handler ( * * args ) :
self . __resetDataset ( )
try :
self . __setWebLang ( args [ " weblang " ] )
del args [ " weblang " ]
except KeyError :
pass
nextTemplate = plugin . doAction ( * * args )
## set the default template
if not nextTemplate : nextTemplate = " form_system "
return self . __render ( nextTemplate , plugin )
return handler
##################### input checker ##########################
def __setWebLang ( self , value ) :
@ -453,6 +370,7 @@ class WebInterfaceSites:
plugin_cs_file = plugin . getTemplateFileName ( template )
if plugin_cs_file :
self . dataset [ " Settings.TemplateFile " ] = plugin_cs_file
## add the current state of the plugins to the hdf dataset
self . dataset [ " Data.Status.Plugins. %s " % plugin . getName ( ) ] = plugin . getStatus ( )
## load the language data
@ -494,31 +412,3 @@ class WebInterfaceSites:
yield line + " \n "
def test_stream ( self ) :
""" just for testing purposes - to check if the " stream_response " feature
actually works - for now ( September 02006 ) it does not seem to be ok """
import time
yield " <html><head><title>neu</title></head><body><p><ul> "
for a in range ( 10 ) :
yield " <li>yes: %d - %s </li> " % ( a , str ( time . time ( ) ) )
time . sleep ( 1 )
yield " </ul></p></html> "
############################################################################
## to make the sites visible through the webserver they must be exposed here
index . exposed = True
doc . exposed = True
system . exposed = True
status . exposed = True
show_volume . exposed = True
volume_name_set . exposed = True
mount_do . exposed = True
volume_init_ask . exposed = True
init_do . exposed = True
umount_do . exposed = True
show_volumes . exposed = True
test . exposed = True
test_stream . exposed = True