Use built-in python functions for authenticating against unix-accounts
[vuplus_dvbapp-plugin] / webinterface / src / plugin.py
index 844e925..17d61f8 100644 (file)
 Version = '$Header$';
-__version__ = "Beta 0.98.1"
+
+from enigma import eConsoleAppContainer, eTPM
 from Plugins.Plugin import PluginDescriptor
-from Components.config import config, ConfigSubsection, ConfigInteger,ConfigYesNo,ConfigText
-from Components.Network import Network
-
-from twisted.internet import reactor, defer
-from twisted.web2 import server, channel, http
-from twisted.web2.auth import digest, basic, wrapper
-#from twisted.python import util
-from twisted.python.log import startLogging
-from twisted.cred.portal import Portal, IRealm
-from twisted.cred import checkers, credentials, error
-from zope.interface import Interface, implements
 
+from Components.config import config, ConfigBoolean, ConfigSubsection, ConfigInteger, ConfigYesNo, ConfigText
+from Components.Network import iNetwork
+from Screens.MessageBox import MessageBox
 from WebIfConfig import WebIfConfigScreen
+from WebChilds.Toplevel import getToplevel
+from Tools.HardwareInfo import HardwareInfo
 
-from WebChilds.Toplevel import Toplevel
+from Tools.Directories import copyfile, resolveFilename, SCOPE_PLUGINS, SCOPE_CONFIG
 
-from Tools.BoundFunction import boundFunction
+from twisted.internet import reactor, ssl
+from twisted.web import server, http, util, static, resource
+
+from zope.interface import Interface, implements
+from socket import gethostname as socket_gethostname
+from OpenSSL import SSL
 
+from os.path import isfile as os_isfile
+from __init__ import _, __version__, decrypt_block
+from webif import get_random, validate_certificate
+
+tpm = eTPM()
+rootkey = ['\x9f', '|', '\xe4', 'G', '\xc9', '\xb4', '\xf4', '#', '&', '\xce', '\xb3', '\xfe', '\xda', '\xc9', 'U', '`', '\xd8', '\x8c', 's', 'o', '\x90', '\x9b', '\\', 'b', '\xc0', '\x89', '\xd1', '\x8c', '\x9e', 'J', 'T', '\xc5', 'X', '\xa1', '\xb8', '\x13', '5', 'E', '\x02', '\xc9', '\xb2', '\xe6', 't', '\x89', '\xde', '\xcd', '\x9d', '\x11', '\xdd', '\xc7', '\xf4', '\xe4', '\xe4', '\xbc', '\xdb', '\x9c', '\xea', '}', '\xad', '\xda', 't', 'r', '\x9b', '\xdc', '\xbc', '\x18', '3', '\xe7', '\xaf', '|', '\xae', '\x0c', '\xe3', '\xb5', '\x84', '\x8d', '\r', '\x8d', '\x9d', '2', '\xd0', '\xce', '\xd5', 'q', '\t', '\x84', 'c', '\xa8', ')', '\x99', '\xdc', '<', '"', 'x', '\xe8', '\x87', '\x8f', '\x02', ';', 'S', 'm', '\xd5', '\xf0', '\xa3', '_', '\xb7', 'T', '\t', '\xde', '\xa7', '\xf1', '\xc9', '\xae', '\x8a', '\xd7', '\xd2', '\xcf', '\xb2', '.', '\x13', '\xfb', '\xac', 'j', '\xdf', '\xb1', '\x1d', ':', '?']
+hw = HardwareInfo()
+#CONFIG INIT
+
+#init the config
 config.plugins.Webinterface = ConfigSubsection()
-config.plugins.Webinterface.enable = ConfigYesNo(default = True)
-config.plugins.Webinterface.port = ConfigInteger(80,limits = (1, 65536))
-config.plugins.Webinterface.includehdd = ConfigYesNo(default = False)
-config.plugins.Webinterface.useauth = ConfigYesNo(default = False) # False, because a std. images hasnt a rootpasswd set and so no login. and a login with a empty pwd makes no sense
-config.plugins.Webinterface.autowritetimer = ConfigYesNo(default = False)
-config.plugins.Webinterface.loadmovielength = ConfigYesNo(default = False)
-config.plugins.Webinterface.debug = ConfigYesNo(default = False) # False by default, not confgurable in GUI. Edit settingsfile directly if needed
-config.plugins.Webinterface.version = ConfigText(__version__) # used to make the versioninfo accessible enigma2-wide, not confgurable in GUI. 
-
-"""
- set DEBUG to True, if twisted should write logoutput to a file.
- in normal console output, twisted will print only the first Traceback.
- is this a bug in twisted or a conflict with enigma2?
- with this option enabled, twisted will print all TB to the logfile
- use tail -f <file> to view this log
-"""
-                       
+config.plugins.Webinterface.enabled = ConfigYesNo(default=True)
+config.plugins.Webinterface.allowzapping = ConfigYesNo(default=True)
+config.plugins.Webinterface.includemedia = ConfigYesNo(default=False)
+config.plugins.Webinterface.autowritetimer = ConfigYesNo(default=False)
+config.plugins.Webinterface.loadmovielength = ConfigYesNo(default=True)
+config.plugins.Webinterface.version = ConfigText(__version__) # used to make the versioninfo accessible enigma2-wide, not confgurable in GUI.
 
-DEBUGFILE= "/tmp/twisted.log"
+config.plugins.Webinterface.http = ConfigSubsection()
+config.plugins.Webinterface.http.enabled = ConfigYesNo(default=True)
+config.plugins.Webinterface.http.port = ConfigInteger(default = 80, limits=(1, 65535) )
+config.plugins.Webinterface.http.auth = ConfigYesNo(default=False)
+
+config.plugins.Webinterface.https = ConfigSubsection()
+config.plugins.Webinterface.https.enabled = ConfigYesNo(default=True)
+config.plugins.Webinterface.https.port = ConfigInteger(default = 443, limits=(1, 65535) )
+config.plugins.Webinterface.https.auth = ConfigYesNo(default=True)
+
+config.plugins.Webinterface.streamauth = ConfigYesNo(default=False)
+
+global running_defered, waiting_shutdown, toplevel
 
-global running_defered,waiting_shutdown
 running_defered = []
 waiting_shutdown = 0
+toplevel = None
+server.VERSION = "Enigma2 WebInterface Server $Revision$".replace("$Revi", "").replace("sion: ", "").replace("$", "")
 
+#===============================================================================
+# Helperclass to close running Instances of the Webinterface
+#===============================================================================
 class Closer:
        counter = 0
-       def __init__(self,session, callback):
+       def __init__(self, session, callback=None, l2k=None):
                self.callback = callback
                self.session = session
-               
+               self.l2k = l2k
+#===============================================================================
+# Closes all running Instances of the Webinterface
+#===============================================================================
        def stop(self):
                global running_defered
                for d in running_defered:
-                       print "[WebIf] STOPPING reactor on interface ",d.interface," with port",d.port
+                       print "[Webinterface] stopping interface on ", d.interface, " with port", d.port
                        x = d.stopListening()
+                       
                        try:
                                x.addCallback(self.isDown)
-                               self.counter +=1
+                               self.counter += 1
                        except AttributeError:
                                pass
                running_defered = []
-               if self.counter <1:
-                       self.callback(self.session)
+               if self.counter < 1:
+                       if self.callback is not None:
+                               self.callback(self.session, self.l2k)
+
+#===============================================================================
+# #Is it already down?
+#===============================================================================
+       def isDown(self, s):
+               self.counter -= 1
+               if self.counter < 1:
+                       if self.callback is not None:
+                               self.callback(self.session, self.l2k)
+
+def checkCertificates():
+       print "[WebInterface] checking for SSL Certificates"
+       srvcert = '%sserver.pem' %resolveFilename(SCOPE_CONFIG) 
+       cacert = '%scacert.pem' %resolveFilename(SCOPE_CONFIG)
+
+       # Check whether there are regular certificates, if not copy the default ones over
+       if not os_isfile(srvcert) or not os_isfile(cacert):
+               return False
+       
+       else:
+               return True
                
-       def isDown(self,s):
-               self.counter-=1
-               if self.counter <1:
-                       self.callback(self.session)
-                       
+def installCertificates(session, callback = None, l2k = None):
+       print "[WebInterface] Installing SSL Certificates to %s" %resolveFilename(SCOPE_CONFIG)
+       
+       srvcert = '%sserver.pem' %resolveFilename(SCOPE_CONFIG) 
+       cacert = '%scacert.pem' %resolveFilename(SCOPE_CONFIG)  
+       scope_webif = '%sExtensions/WebInterface/' %resolveFilename(SCOPE_PLUGINS)
+       
+       source = '%setc/server.pem' %scope_webif
+       target = srvcert
+       ret = copyfile(source, target)
+       
+       if ret == 0:
+               source = '%setc/cacert.pem' %scope_webif
+               target = cacert
+               ret = copyfile(source, target)
                
-def restartWebserver(session):
+               if ret == 0 and callback != None:
+                       callback(session, l2k)
+       
+       if ret < 0:
+               config.plugins.Webinterface.https.enabled.value = False
+               config.plugins.Webinterface.https.enabled.save()
+               
+               # Start without https
+               callback(session, l2k)
+               
+               #Inform the user
+               session.open(MessageBox, "Couldn't install SSL-Certifactes for https access\nHttps access is now disabled!", MessageBox.TYPE_ERROR)
+       
+#===============================================================================
+# restart the Webinterface for all configured Interfaces
+#===============================================================================
+def restartWebserver(session, l2k):
        try:
                del session.mediaplayer
                del session.messageboxanswer
@@ -81,255 +147,342 @@ def restartWebserver(session):
                pass
 
        global running_defered
-       if len(running_defered) >0:
-               Closer(session,startWebserver).stop()
+       if len(running_defered) > 0:
+               Closer(session, startWebserver, l2k).stop()
        else:
-               startWebserver(session)
-
-def startWebserver(session):
+               startWebserver(session, l2k)
+       
+#===============================================================================
+# start the Webinterface for all configured Interfaces
+#===============================================================================
+def startWebserver(session, l2k):
        global running_defered
+       global toplevel
        
-       # variables, that are needed in the process
        session.mediaplayer = None
        session.messageboxanswer = None
+       if toplevel is None:
+               toplevel = getToplevel(session)
        
-       if config.plugins.Webinterface.enable.value is not True:
-               print "not starting Werbinterface"
-               return False
-       if config.plugins.Webinterface.debug.value:
-               print "start twisted logfile, writing to %s" % DEBUGFILE 
-               startLogging(open(DEBUGFILE,'w'))
-
-       toplevel = Toplevel(session)
-       if config.plugins.Webinterface.useauth.value is False:
-               site = server.Site(toplevel)
-       else:
-               portal = Portal(HTTPAuthRealm())
-               portal.registerChecker(PasswordDatabase())
-               root = ModifiedHTTPAuthResource(toplevel,(basic.BasicCredentialFactory('DM7025'),),portal, (IHTTPUser,))
-               site = server.Site(root)
+       errors = ""
        
-       # here we start the Toplevel without any username or password
-       # this allows access to all request over the iface 127.0.0.1 without any auth
-       localsite = server.Site(toplevel)
-       d = reactor.listenTCP(config.plugins.Webinterface.port.value, channel.HTTPFactory(localsite),interface='127.0.0.1')
-       running_defered.append(d)
-       # and here we make the Toplevel public to our external ifaces
-       # it depends on the config, if this is with auth support
-       # keep in mind, if we have a second external ip (like a wlan device), we have to do it in the same way for this iface too
-       nw = Network()
-       for adaptername in nw.ifaces:
-               extip = nw.ifaces[adaptername]['ip']
-               if nw.ifaces[adaptername]['up'] is True:
-                       extip = "%i.%i.%i.%i"%(extip[0],extip[1],extip[2],extip[3])
-                       print "[WebIf] starting Webinterface on port %s on interface %s with address %s"%(str(config.plugins.Webinterface.port.value),adaptername,extip)
-                       try:
-                               d = reactor.listenTCP(config.plugins.Webinterface.port.value, channel.HTTPFactory(site),interface=extip)
-                               running_defered.append(d)
-                       except Exception,e:
-                               print "[WebIf] Error starting Webinterface on port %s on interface %s with address %s,because \n%s"%(str(config.plugins.Webinterface.port.value),adaptername,extip,e)
-               else:
-                       print "[WebIf] found configured interface %s, but it is not running. so not starting a server on it ..." % adaptername
+       if config.plugins.Webinterface.enabled.value is not True:
+               print "[Webinterface] is disabled!"
        
-####           
-def autostart(reason, **kwargs):
-       if "session" in kwargs:
-               try:
-                       startWebserver(kwargs["session"])
-               except ImportError,e:
-                       print "[WebIf] twisted not available, not starting web services",e
+       else:
+               # IF SSL is enabled we need to check for the certs first
+               # If they're not there we'll exit via return here 
+               # and get called after Certificates are installed properly
+               if config.plugins.Webinterface.https.enabled.value:
+                       if not checkCertificates():
+                               print "[Webinterface] Installing Webserver Certificates for SSL encryption"
+                               installCertificates(session, startWebserver, l2k)
+                               return
+               # Listen on all Interfaces
+               ip = "0.0.0.0"
+               #HTTP
+               if config.plugins.Webinterface.http.enabled.value is True:
+                       ret = startServerInstance(session, ip, config.plugins.Webinterface.http.port.value, config.plugins.Webinterface.http.auth.value, l2k)
+                       if ret == False:
+                               errors = "%s%s:%i\n" %(errors, ip, config.plugins.Webinterface.http.port.value)
+                       else:
+                               registerBonjourService('http', config.plugins.Webinterface.http.port.value)
                        
-def openconfig(session, **kwargs):
-       session.openWithCallback(configCB,WebIfConfigScreen)
+               #Streaming requires listening on 127.0.0.1:80 no matter what, ensure it its available
+               if config.plugins.Webinterface.http.port.value != 80 or not config.plugins.Webinterface.http.enabled.value:
+                       #LOCAL HTTP Connections (Streamproxy)
+                       ret = startServerInstance(session, '127.0.0.1', 80, config.plugins.Webinterface.http.auth.value, l2k)                   
+                       if ret == False:
+                               errors = "%s%s:%i\n" %(errors, '127.0.0.1', 80)
+                       
+                       if errors != "":
+                               session.open(MessageBox, "Webinterface - Couldn't listen on:\n %s" % (errors), type=MessageBox.TYPE_ERROR, timeout=30)
+                               
+               #HTTPS          
+               if config.plugins.Webinterface.https.enabled.value is True:                                     
+                       ret = startServerInstance(session, ip, config.plugins.Webinterface.https.port.value, config.plugins.Webinterface.https.auth.value, l2k, True)
+                       if ret == False:
+                               errors = "%s%s:%i\n" %(errors, ip, config.plugins.Webinterface.https.port.value)
+                       else:
+                               registerBonjourService('https', config.plugins.Webinterface.https.port.value)
+               
+#===============================================================================
+# stop the Webinterface for all configured Interfaces
+#===============================================================================
+def stopWebserver(session):
+       try:
+               del session.mediaplayer
+               del session.messageboxanswer
+       except NameError:
+               pass
+       except AttributeError:
+               pass
 
-def configCB(result,session):
-       if result is True:
-               print "[WebIf] config changed"
-               restartWebserver(session)
-       else:
-               print "[WebIf] config not changed"
+       global running_defered
+       if len(running_defered) > 0:
+               Closer(session).stop()
+
+#===============================================================================
+# startServerInstance
+# Starts an Instance of the Webinterface
+# on given ipaddress, port, w/o auth, w/o ssl
+#===============================================================================
+def startServerInstance(session, ipaddress, port, useauth=False, l2k=None, usessl=False):
+       if hw.get_device_name().lower() != "dm7025":
+               l3k = None              
+               l3c = tpm.getCert(eTPM.TPMD_DT_LEVEL3_CERT)
+               
+               if l3c is None:
+                       return False                    
+               
+               l3k = validate_certificate(l3c, l2k)
+               if l3k is None:                 
+                       return False
                
+               random = get_random()
+               if random is None:
+                       return False
+       
+               value = tpm.challenge(random)
+               result = decrypt_block(value, l3k)
+               
+               if result is None:
+                       return False
+               else:
+                       if result [80:88] != random:            
+                               return False
+               
+       if useauth:
+# HTTPAuthResource handles the authentication for every Resource you want it to                        
+               root = HTTPAuthResource(toplevel, "Enigma2 WebInterface")
+               site = server.Site(root)                        
+       else:
+               site = server.Site(toplevel)
 
-def Plugins(**kwargs):
-       return [PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART, PluginDescriptor.WHERE_AUTOSTART], fnc = autostart),
-                   PluginDescriptor(name=_("Webinterface"), description=_("Configuration for the Webinterface"),where = [PluginDescriptor.WHERE_PLUGINMENU], icon="plugin.png",fnc = openconfig)]
+       if usessl:
+               
+               ctx = ssl.DefaultOpenSSLContextFactory('/etc/enigma2/server.pem', '/etc/enigma2/cacert.pem', sslmethod=SSL.SSLv23_METHOD)
+               d = reactor.listenSSL(port, site, ctx, interface=ipaddress)
+       else:
+               d = reactor.listenTCP(port, site, interface=ipaddress)
+       running_defered.append(d)               
+       print "[Webinterface] started on %s:%i auth=%s ssl=%s" % (ipaddress, port, useauth, usessl)
+       return True
        
+       #except Exception, e:
+               #print "[Webinterface] starting FAILED on %s:%i!" % (ipaddress, port), e                
+               #return False
+#===============================================================================
+# HTTPAuthResource
+# Handles HTTP Authorization for a given Resource
+#===============================================================================
+class HTTPAuthResource(resource.Resource):
+       def __init__(self, res, realm):
+               resource.Resource.__init__(self)
+               self.resource = res
+               self.realm = realm
+               self.authorized = False
+               self.tries = 0
+               self.unauthorizedResource = UnauthorizedResource(self.realm)
        
-class ModifiedHTTPAuthResource(wrapper.HTTPAuthResource):
-       """
-               set it only to True, if you have a patched wrapper.py
-               see http://twistedmatrix.com/trac/ticket/2041
-               so, the solution for us is to make a new class an override ne faulty func
-       """
-
-       def locateChild(self, req, seg):
-               return self.authenticate(req), seg
+       def unautorized(self, request):
+               request.setResponseCode(http.UNAUTHORIZED)
+               request.setHeader('WWW-authenticate', 'basic realm="%s"' % self.realm)
+
+               return self.unauthorizedResource
+       
+       def isAuthenticated(self, request):             
+               host = request.getHost().host
+               #If streamauth is disabled allow all acces from localhost
+               if not config.plugins.Webinterface.streamauth.value:                    
+                       if( host == "127.0.0.1" or host == "localhost" ):
+                               print "[WebInterface.plugin.isAuthenticated] Streaming auth is disabled bypassing authcheck because host is '%s'" %host
+                               return True
+                                       
+               # get the Session from the Request
+               sessionNs = request.getSession().sessionNamespaces
+               
+               # if the auth-information has not yet been stored to the session
+               if not sessionNs.has_key('authenticated'):
+                       if request.getUser() != '':
+                               sessionNs['authenticated'] = check_passwd(request.getUser(), request.getPassword())
+                       else:
+                               sessionNs['authenticated'] = False
+               
+               #if the auth-information already is in the session                              
+               else:
+                       if sessionNs['authenticated'] is False:
+                               sessionNs['authenticated'] = check_passwd(request.getUser(), request.getPassword() )
+               
+               #return the current authentication status                                               
+               return sessionNs['authenticated']
+                                                                                                       
+#===============================================================================
+# Call render of self.resource (if authenticated)                                                                                                      
+#===============================================================================
+       def render(self, request):                      
+               if self.isAuthenticated(request) is True:       
+                       return self.resource.render(request)
+               
+               else:
+                       print "[Webinterface.HTTPAuthResource.render] !!! unauthorized !!!"
+                       return self.unautorized(request).render(request)
+
+#===============================================================================
+# Override to call getChildWithDefault of self.resource (if authenticated)     
+#===============================================================================
+       def getChildWithDefault(self, path, request):
+               if self.isAuthenticated(request) is True:
+                       return self.resource.getChildWithDefault(path, request)
+               
+               else:
+                       print "[Webinterface.HTTPAuthResource.render] !!! unauthorized !!!"
+                       return self.unautorized(request)
+
+#===============================================================================
+# UnauthorizedResource
+# Returns a simple html-ified "Access Denied"
+#===============================================================================
+class UnauthorizedResource(resource.Resource):
+       def __init__(self, realm):
+               resource.Resource.__init__(self)
+               self.realm = realm
+               self.errorpage = static.Data('<html><body>Access Denied.</body></html>', 'text/html')
        
-class PasswordDatabase:
-    """
-       this checks webiflogins agains /etc/passwd
-    """
-    passwordfile = "/etc/passwd"
-    implements(checkers.ICredentialsChecker)
-    credentialInterfaces = (credentials.IUsernamePassword,credentials.IUsernameHashedPassword)
-
-    def _cbPasswordMatch(self, matched, username):
-        if matched:
-            return username
-        else:
-            return failure.Failure(error.UnauthorizedLogin())
-
-    def requestAvatarId(self, credentials):    
-       if check_passwd(credentials.username,credentials.password,self.passwordfile) is True:
-               return defer.maybeDeferred(credentials.checkPassword,credentials.password).addCallback(self._cbPasswordMatch, str(credentials.username))
-       else:
-               return defer.fail(error.UnauthorizedLogin())
-
-class IHTTPUser(Interface):
-       pass
-
-class HTTPUser(object):
-       implements(IHTTPUser)
-
-class HTTPAuthRealm(object):
-       implements(IRealm)
-       def requestAvatar(self, avatarId, mind, *interfaces):
-               if IHTTPUser in interfaces:
-                       return IHTTPUser, HTTPUser()
-               raise NotImplementedError("Only IHTTPUser interface is supported")
-
-
-from string import find, split 
-from md5 import new as md5_new
+       def getChild(self, path, request):
+               return self.errorpage
+               
+       def render(self, request):      
+               return self.errorpage.render(request)
+
+
+
+# Password verfication stuff
 from crypt import crypt
+from pwd import getpwnam
+from spwd import getspnam
+
+
+def check_passwd(name, passwd):
+       cryptedpass = None
+       try:
+               cryptedpass = getpwnam(name)[1]
+       except:
+               return False
+       
+       if cryptedpass:
+               #shadowed or not, that's the questions here
+               if cryptedpass == 'x' or cryptedpass == '*':
+                       try:
+                               cryptedpass = getspnam(name)[1]
+                       except:
+                               return False                    
+                               
+               return crypt(passwd, cryptedpass) == cryptedpass
+       return False
+
+global_session = None
+
+#===============================================================================
+# sessionstart
+# Actions to take place on Session start 
+#===============================================================================
+def sessionstart(reason, session):
+       global global_session
+       global_session = session
+
 
-DES_SALT = list('./0123456789' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz') 
-def getpwnam(name, pwfile=None):
-    """Return pasword database entry for the given user name.
-    
-    Example from the Python Library Reference.
-    """
-    
-    if not pwfile:
-        pwfile = '/etc/passwd'
-
-    f = open(pwfile)
-    while 1:
-        line = f.readline()
-        if not line:
-            f.close()
-            raise KeyError, name
-        entry = tuple(line.strip().split(':', 6))
-        if entry[0] == name:
-            f.close()
-            return entry
-
-def passcrypt(passwd, salt=None, method='des', magic='$1$'):
-    """Encrypt a string according to rules in crypt(3)."""
-    if method.lower() == 'des':
-           return crypt(passwd, salt)
-    elif method.lower() == 'md5':
-       return passcrypt_md5(passwd, salt, magic)
-    elif method.lower() == 'clear':
-        return passwd
-
-def check_passwd(name, passwd, pwfile=None):
-    """Validate given user, passwd pair against password database."""
-    
-    if not pwfile or type(pwfile) == type(''):
-        getuser = lambda x,pwfile=pwfile: getpwnam(x,pwfile)[1]
-    else:
-        getuser = pwfile.get_passwd
-
-    try:
-        enc_passwd = getuser(name)
-    except (KeyError, IOError):
-        return 0
-    if not enc_passwd:
-        return 0
-    elif len(enc_passwd) >= 3 and enc_passwd[:3] == '$1$':
-        salt = enc_passwd[3:find(enc_passwd, '$', 3)]
-        return enc_passwd == passcrypt(passwd, salt, 'md5')
-       
-    else:
-        return enc_passwd == passcrypt(passwd, enc_passwd[:2])
-
-def _to64(v, n):
-    r = ''
-    while (n-1 >= 0):
-       r = r + DES_SALT[v & 0x3F]
-       v = v >> 6
-       n = n - 1
-    return r
+def registerBonjourService(protocol, port):    
+       try:
+               from Plugins.Extensions.Bonjour.Bonjour import bonjour
+                               
+               service = bonjour.buildService(protocol, port)
+               bonjour.registerService(service, True)
+               print "[WebInterface.registerBonjourService] Service for protocol '%s' with port '%i' registered!" %(protocol, port) 
+               return True
+               
+       except ImportError, e:
+               print "[WebInterface.registerBonjourService] %s" %e
+               return False
+
+def unregisterBonjourService(protocol):        
+       try:
+               from Plugins.Extensions.Bonjour.Bonjour import bonjour
+                                               
+               bonjour.unregisterService(protocol)
+               print "[WebInterface.unregisterBonjourService] Service for protocol '%s' unregistered!" %(protocol) 
+               return True
+               
+       except ImportError, e:
+               print "[WebInterface.unregisterBonjourService] %s" %e
+               return False
+       
+def checkBonjour():
+       if ( not config.plugins.Webinterface.http.enabled.value ) or ( not config.plugins.Webinterface.enabled.value ):
+               unregisterBonjourService('http')
+       if ( not config.plugins.Webinterface.https.enabled.value ) or ( not config.plugins.Webinterface.enabled.value ):
+               unregisterBonjourService('https')
+               
+#===============================================================================
+# networkstart
+# Actions to take place after Network is up (startup the Webserver)
+#===============================================================================
+def networkstart(reason, **kwargs):
+       l2r = False
+       l2k = None
+       if hw.get_device_name().lower() != "dm7025":            
+               l2c = tpm.getCert(eTPM.TPMD_DT_LEVEL2_CERT)
+               
+               if l2c is None:
+                       return
+               
+               l2k = validate_certificate(l2c, rootkey)
+               if l2k is None:
+                       return
                        
-def passcrypt_md5(passwd, salt=None, magic='$1$'):
-    """Encrypt passwd with MD5 algorithm."""
-    
-    if not salt:
-       pass
-    elif salt[:len(magic)] == magic:
-        # remove magic from salt if present
-        salt = salt[len(magic):]
-
-    # salt only goes up to first '$'
-    salt = split(salt, '$')[0]
-    # limit length of salt to 8
-    salt = salt[:8]
-
-    ctx = md5_new(passwd)
-    ctx.update(magic)
-    ctx.update(salt)
-    
-    ctx1 = md5_new(passwd)
-    ctx1.update(salt)
-    ctx1.update(passwd)
-    
-    final = ctx1.digest()
-    
-    for i in range(len(passwd), 0 , -16):
-       if i > 16:
-           ctx.update(final)
-       else:
-           ctx.update(final[:i])
-    
-    i = len(passwd)
-    while i:
-       if i & 1:
-           ctx.update('\0')
-       else:
-           ctx.update(passwd[:1])
-       i = i >> 1
-    final = ctx.digest()
-    
-    for i in range(1000):
-       ctx1 = md5_new()
-       if i & 1:
-           ctx1.update(passwd)
+               l2r = True
        else:
-           ctx1.update(final)
-       if i % 3: ctx1.update(salt)
-       if i % 7: ctx1.update(passwd)
-       if i & 1:
-           ctx1.update(final)
-       else:
-           ctx1.update(passwd)
-        final = ctx1.digest()
-    
-    rv = magic + salt + '$'
-    final = map(ord, final)
-    l = (final[0] << 16) + (final[6] << 8) + final[12]
-    rv = rv + _to64(l, 4)
-    l = (final[1] << 16) + (final[7] << 8) + final[13]
-    rv = rv + _to64(l, 4)
-    l = (final[2] << 16) + (final[8] << 8) + final[14]
-    rv = rv + _to64(l, 4)
-    l = (final[3] << 16) + (final[9] << 8) + final[15]
-    rv = rv + _to64(l, 4)
-    l = (final[4] << 16) + (final[10] << 8) + final[5]
-    rv = rv + _to64(l, 4)
-    l = final[11]
-    rv = rv + _to64(l, 2)
-    
-    return rv
+               l2r = True
+               
+       if l2r: 
+               if reason is True:
+                       startWebserver(global_session, l2k)
+                       checkBonjour()
+                       
+               elif reason is False:
+                       stopWebserver(global_session)
+                       checkBonjour()
+               
+def openconfig(session, **kwargs):
+       session.openWithCallback(configCB, WebIfConfigScreen)
 
+def configCB(result, session):
+       l2r = False
+       l2k = None
+       if hw.get_device_name().lower() != "dm7025":            
+               l2c = tpm.getCert(eTPM.TPMD_DT_LEVEL2_CERT)
+               
+               if l2c is None:
+                       return
+               
+               l2k = validate_certificate(l2c, rootkey)
+               if l2k is None:
+                       return
+                       
+               l2r = True
+       else:
+               l2r = True
+               
+       if l2r: 
+               if result:
+                       print "[WebIf] config changed"
+                       restartWebserver(session, l2k)
+                       checkBonjour()
+               else:
+                       print "[WebIf] config not changed"
 
+def Plugins(**kwargs):
+       return [PluginDescriptor(where=[PluginDescriptor.WHERE_SESSIONSTART], fnc=sessionstart),
+                       PluginDescriptor(where=[PluginDescriptor.WHERE_NETWORKCONFIG_READ], fnc=networkstart),
+                       PluginDescriptor(name=_("Webinterface"), description=_("Configuration for the Webinterface"),
+                                                       where=[PluginDescriptor.WHERE_PLUGINMENU], icon="plugin.png", fnc=openconfig)]