fix bluescreen, Security service not running
[enigma2-plugins.git] / genuinedreambox / src / plugin.py
1 # -*- coding: utf-8 -*-
2 ###########################################################################
3 #
4 # http://newnigma2.to
5 #
6 # $Id:
7 #
8 # Copyright (C) 2009 by
9 # <nixkoenner@newnigma2.to>
10 #
11 #       License: GPL
12 #
13 #       This program is free software; you can redistribute it and/or modify
14 #       it under the terms of the GNU General Public License as published by
15 #       the Free Software Foundation; either version 2 of the License, or
16 #       (at your option) any later version.
17 #
18 #       This program is distributed in the hope that it will be useful,
19 #       but WITHOUT ANY WARRANTY; without even the implied warranty of
20 #       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 #       GNU General Public License for more details.
22 #
23 #       You should have received a copy of the GNU General Public License
24 #       along with this program; if not, write to the Free Software
25 #       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #
27 ###########################################################################
28 #
29 # thx to <kayshadow@newnigma2.to> for painting the icon 
30 #
31 from Plugins.Plugin import PluginDescriptor
32 from Screens.Screen import Screen
33
34 from Components.ActionMap import ActionMap
35 from Components.Button import Button
36 from Components.Label import Label 
37
38 import socket
39 import struct
40 import base64
41
42 from twisted.web.client import getPage
43
44 TPMD_DT_RESERVED = 0x00
45 TPMD_DT_PROTOCOL_VERSION = 0x01
46 TPMD_DT_TPM_VERSION    = 0x02
47 TPMD_DT_SERIAL = 0x03
48 TPMD_DT_LEVEL2_CERT = 0x04
49 TPMD_DT_LEVEL3_CERT    = 0x05
50 TPMD_DT_FAB_CA_CERT    = 0x06
51 TPMD_DT_DATABLOCK_SIGNED = 0x07
52 TPMD_CMD_RESERVED    = 0x0000
53 TPMD_CMD_GET_DATA    = 0x0001
54 TPMD_CMD_APDU    = 0x0002
55 TPMD_CMD_COMPUTE_SIGNATURE = 0x0003
56
57 class genuineDreambox(Screen):
58     skin = """
59         <screen position="60,80" size="620,420" title="%s" >
60         <widget name="infotext" position="10,20" zPosition="1" size="600,150" font="Regular;20" halign="center" valign="center" />
61         <widget name="resulttext" position="10,160" zPosition="1" size="600,110" font="Regular;20" halign="center" valign="center" />
62         <widget name="infotext2" position="10,280" zPosition="1" size="600,80" font="Regular;20" halign="center" valign="center" />
63         <widget name="kRed" position="185,365" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />       
64         <ePixmap name="red" position="185,365" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
65         <widget name="kGreen" position="330,365" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
66         <ePixmap name="green" position="330,365" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
67         </screen>"""% _("Genuine Dreambox")
68
69     def __init__(self, session):
70         Screen.__init__(self, session)
71         self["actions"] = ActionMap(["SetupActions", "ColorActions"],
72         {
73             "green": self.restart,
74             "cancel": self.close,
75          }, -1)
76         self["kGreen"] = Button(_("Restart"))
77         self["kRed"] = Button(_("Cancel"))
78         self["infotext"] = Label("With this plugin you can verify the authenticity of your Dreambox.\nFor additional information, \nplease visit our website \nhttps://www.dream-multimedia-tv.de.")
79         self["resulttext"] = Label("... Please wait ...")
80         self["infotext2"] = Label("Please visit our website and follow the instructions.\nAlternatively you can call our customer service hotline.")
81         self.onLayoutFinish.append(self.start)
82
83     def restart(self):
84         if not self.isStart:
85             self.start()
86    
87     def start(self):
88         udsError = False
89         self.isStart = True
90         try:
91             self["resulttext"].setText("Please wait (Step 1)")
92             self.uds = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
93             self.uds.connect(("/var/run/tpmd_socket"))
94         except:
95             self["resulttext"].setText("Security service not running.")
96             udsError = True
97         if not udsError:
98             if (self.stepFirst(TPMD_CMD_GET_DATA,[TPMD_DT_PROTOCOL_VERSION,TPMD_DT_TPM_VERSION,TPMD_DT_SERIAL])):
99                 try:  
100                     url = ("https://www.dream-multimedia-tv.de/verify/challenge?serial=%s&version=%s" % (self.serial,self.tpmdVersion))
101                     getPage(url).addCallback(self._gotPageLoadRandom).addErrback(self.errorLoad)
102                 except:
103                     self["resulttext"].setText("Can't connect to server. Please check your network!")
104
105     def _gotPageLoad(self, data):
106         authcode = data.strip().replace('+', '')
107         self.finish = "%s-%s-%s" % (authcode[0:4], authcode[4:8], authcode[8:12])
108         self["resulttext"].setText(self.finish)
109         self.isStart = False
110         
111     def _gotPageLoadRandom(self, data):
112         self["resulttext"].setText("Please wait (Step 2)")
113         self.back = data.strip()
114         self.random = (self.formatList(base64.b64decode(self.back)))
115         self.stepSecond(TPMD_CMD_GET_DATA,[TPMD_DT_PROTOCOL_VERSION,TPMD_DT_TPM_VERSION,TPMD_DT_SERIAL,TPMD_DT_LEVEL2_CERT,
116                 TPMD_DT_LEVEL3_CERT,TPMD_DT_FAB_CA_CERT,TPMD_DT_DATABLOCK_SIGNED] )
117         url = self.buildUrl()
118         getPage(url).addCallback(self._gotPageLoad).addErrback(self.errorLoad) 
119
120     def errorLoad(self, error):
121         self["resulttext"].setText("Invalid response from server. Please report: %s" % str(error))
122
123     def buildUrl(self):
124         # NOTE: this is a modified base64 which uses -_ instead of +/ to avoid the need for escpaing + when using urlencode 
125         tmpra = ("random=%s" % self.back.replace('+', '-').replace('/', '_'))
126         tmpl2 = ("&l2=%s" % base64.b64encode(self.level2_cert).replace('+', '-').replace('/', '_'))
127         if self.level3_cert:
128             tmpl3 = ("&l3=%s" % base64.b64encode(self.level3_cert).replace('+', '-').replace('/', '_'))
129         else:
130             tmpl3 = ""
131         tmpfa = ("&fab=%s" % base64.b64encode(self.fab_ca_cert).replace('+', '-').replace('/', '_'))
132         tmpda = ("&data=%s" % base64.b64encode(self.datablock_signed).replace('+', '-').replace('/', '_'))
133         tmpr  = ("&r=%s" % base64.b64encode(self.r).replace('+', '-').replace('/', '_'))
134         return("https://www.dream-multimedia-tv.de/verify/challenge?%s%s%s%s%s%s&serial=%s" % (tmpra,tmpl2,tmpl3,tmpfa,tmpda,tmpr,self.serial))
135
136     def formatList(self,l):
137         liste = []
138         for x in l:
139             liste.append(ord(x))
140         return liste
141     
142     def formatString(self,s):
143         myString = ""
144         for x in s:
145             myString =  myString + chr(x)
146         return myString
147
148     def stepFirst(self,typ,daten):
149         return (self.parseResult (self.udsSend(typ,daten,len(daten)), 1))
150
151     def stepSecond(self,typ,daten):
152         self.parseResult(self.udsSend(typ,daten,len(daten)),2)
153         self.parseResult(self.udsSend(TPMD_CMD_COMPUTE_SIGNATURE,self.random,8),3)
154
155     def parseResult(self,rbuf,art):
156         if (rbuf != -1):
157             buf = self.formatList(rbuf)
158             if (art == 1):
159                 self.serial ="%d" % ((buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11])
160                 self.tpmdVersion = "%d" % (buf[1])
161                 self.protocolVersion = "%d" % buf[0]
162                 #print "serial:%s, version:%s, prot_version:%s" % (self.serial,self.tpmdVersion,self.protocolVersion)
163                 return True
164             elif (art == 2):
165                 tpmdata = {}
166                 while len(buf):
167                     type = buf[0]
168                     l = buf[1]
169                     data = ''.join([chr(x) for x in buf[2:l+2]])
170                     buf = buf[l+2:]
171                     tpmdata[type] = data
172                 
173                 self.level2_cert = tpmdata.get(4)
174                 self.level3_cert = tpmdata.get(5) # can be None
175                 self.fab_ca_cert = tpmdata.get(6)
176                 self.datablock_signed = tpmdata.get(7)                
177             elif (art == 3):
178                 self.r = self.formatString(buf)
179         else:
180             return False
181
182     def udsSend(self, cmdTyp, data, length):
183         sbuf = [(cmdTyp >> 8) & 0xff,(cmdTyp >> 0) & 0xff,(length >> 8) & 0xff,(length >> 0) & 0xff]
184         sbuf.extend(data[:length])
185         sbuf = struct.pack(str((length + 4))+"B", *sbuf)
186         self.uds.send(sbuf)
187         rbuf = self.uds.recv(4)
188         leng = [ord(rbuf[2]) << 8 | ord(rbuf[3])]
189         if (leng != 4):
190             res = self.uds.recv(leng[0])
191         else:
192             return -1
193         return res
194
195 def main(session, **kwargs):
196         session.open(genuineDreambox)
197
198 def Plugins(path,**kwargs):
199         global plugin_path
200         plugin_path = path
201         return [
202                 PluginDescriptor(name="Genuine Dreambox", description="Genuine Dreambox",where = PluginDescriptor.WHERE_PLUGINMENU, icon="genuine.png", fnc=main),
203                 PluginDescriptor(name="Genuine Dreambox", where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=main)
204                 ]