diff --git a/rdpy/__init__.py b/rdpy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/rdpy/__init__.pyc b/rdpy/__init__.pyc new file mode 100644 index 0000000..b8443e7 Binary files /dev/null and b/rdpy/__init__.pyc differ diff --git a/rdpy/main.py b/rdpy/main.py new file mode 100644 index 0000000..ae5677f --- /dev/null +++ b/rdpy/main.py @@ -0,0 +1,36 @@ +''' +Created on 4 sept. 2013 + +@author: sylvain +''' +import sys +from PyQt4 import QtGui +from rdpy.qt import adaptor, widget +from rdpy.protocols.rfb import rfb, factory +from rdpy.protocols.rdp import tpkt, tpdu +from twisted.internet import ssl +from OpenSSL import SSL + +class ClientTLSContext(ssl.ClientContextFactory): + isClient = 1 + def getContext(self): + context = SSL.Context(SSL.TLSv1_METHOD) + context.set_options(SSL.OP_DONT_INSERT_EMPTY_FRAGMENTS) + context.set_options(SSL.OP_TLS_BLOCK_PADDING_BUG) + return context + +if __name__ == '__main__': + #app = QtGui.QApplication(sys.argv) + #import qt4reactor + #qt4reactor.install() + + #protocol = rfb.Rfb(rfb.Rfb.CLIENT) + #w = widget.QRemoteDesktop(adaptor.RfbAdaptor(protocol)) + #w.resize(1000, 700) + #w.setWindowTitle('QVNCViewer') + #w.show() + from twisted.internet import reactor + #reactor.connectTCP("127.0.0.1", 5901, factory.RfbFactory(protocol)) + reactor.connectTCP("192.168.122.184", 3389, factory.RfbFactory(tpkt.TPKT(tpdu.TPDU()))) + reactor.run() + sys.exit(app.exec_()) \ No newline at end of file diff --git a/rdpy/protocols/__init__.py b/rdpy/protocols/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/rdpy/protocols/__init__.pyc b/rdpy/protocols/__init__.pyc new file mode 100644 index 0000000..35a4dc2 Binary files /dev/null and b/rdpy/protocols/__init__.pyc differ diff --git a/rdpy/protocols/common/__init__.py b/rdpy/protocols/common/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/rdpy/protocols/common/__init__.pyc b/rdpy/protocols/common/__init__.pyc new file mode 100644 index 0000000..7bf028d Binary files /dev/null and b/rdpy/protocols/common/__init__.pyc differ diff --git a/rdpy/protocols/common/layer.py b/rdpy/protocols/common/layer.py new file mode 100644 index 0000000..9859564 --- /dev/null +++ b/rdpy/protocols/common/layer.py @@ -0,0 +1,38 @@ +''' +Created on 5 sept. 2013 + +@author: sylvain +''' + +class Layer(object): + ''' + classdocs + ''' + def __init__(self, presentation = None): + ''' + Constructor + ''' + self._presentation = presentation + self._transport= None + if not self._presentation is None: + self._presentation._transport = self + + def connect(self): + ''' + signal that the transport layer is OK + ''' + if not self._presentation is None: + self._presentation.connect() + + def read(self, data): + ''' + signal that data is available for this layer + ''' + if not self._presentation is None: + self._presentation.read(data) + + def write(self, data): + ''' + write using transport layer + ''' + self.transport.write(data) \ No newline at end of file diff --git a/rdpy/protocols/common/layer.pyc b/rdpy/protocols/common/layer.pyc new file mode 100644 index 0000000..5a268da Binary files /dev/null and b/rdpy/protocols/common/layer.pyc differ diff --git a/rdpy/protocols/common/protocolbuffer.py b/rdpy/protocols/common/protocolbuffer.py new file mode 100644 index 0000000..93997a2 --- /dev/null +++ b/rdpy/protocols/common/protocolbuffer.py @@ -0,0 +1,49 @@ +''' +Created on 17 aout 2013 + +@author: sylvain +''' +from twisted.internet import protocol +from stream import Stream + +class ProtocolBuffer(protocol.Protocol): + ''' + classdocs + ''' + def __init__(self): + ''' + Constructor + ''' + #data buffer received from twisted network layer + self._buffer = "" + + #len of next packet pass to next state function + self._expectedLen = 0 + + def dataReceived(self, data): + ''' + inherit from protocol class + main event of received data + ''' + self._buffer += data + while len(self._buffer) >= self._expectedLen: + expectedData = Stream(self._buffer[0:self._expectedLen]) + self._buffer = self._buffer[self._expectedLen:] + self.recv(expectedData) + + def expect(self, expectedLen, callback = None): + ''' + newt expected len + ''' + self._expectedLen = expectedLen + + if callback is None: + callback = self.__class__.recv + + self.recv = callback + + def recv(self, data): + ''' + call when expected data is receive + ''' + pass \ No newline at end of file diff --git a/rdpy/protocols/common/protocolbuffer.pyc b/rdpy/protocols/common/protocolbuffer.pyc new file mode 100644 index 0000000..eb90fd4 Binary files /dev/null and b/rdpy/protocols/common/protocolbuffer.pyc differ diff --git a/rdpy/protocols/common/stream.py b/rdpy/protocols/common/stream.py new file mode 100644 index 0000000..340dc23 --- /dev/null +++ b/rdpy/protocols/common/stream.py @@ -0,0 +1,70 @@ +''' +Created on 12 aout 2013 + +@author: sylvain +''' +import struct +from StringIO import StringIO + +class Stream(StringIO): + + def dataLen(self): + return self.len - self.pos + + def read_uint8(self): + return struct.unpack("B",self.read(1))[0] + + def read_beuint16(self): + return struct.unpack(">H",self.read(2))[0] + + def read_leuint16(self): + return struct.unpack("I",'\x00'+self.read(3))[0] + + def read_leuint24(self): + return struct.unpack("I",self.read(4))[0] + + def read_leuint32(self): + return struct.unpack("i",self.read(4))[0] + + def read_lesint32(self): + return struct.unpack("H", value)) + + def write_leuint16(self, value): + self.write(struct.pack("I", value)[1:]) + + def write_beuint32(self, value): + self.write(struct.pack(">I", value)) + + def write_leuint32(self, value): + self.write(struct.pack("i", value)) + + def write_lesint32(self, value): + self.write(struct.pack(" 0: + securityList.append(data.read_uint8()) + #select high security level + for s in securityList: + if s in [SecurityType.NONE, SecurityType.VNC] and s > self._securityLevel: + self._securityLevel = s + break + #send back security level choosen + s = Stream() + s.write_uint8(self._securityLevel) + self.transport.write(s.getvalue()) + self.expect(4, self.readSecurityResult) + + def readSecurityResult(self, data): + ''' + Read security result packet + ''' + result = data.read_beuint32() + if result == 1: + print "Authentification failed" + if self._version == ProtocolVersion.RFB003008: + self.expectWithHeader(4, self.readSecurityFailed) + else: + print "Authentification OK" + self.writeClientInit() + + def readSecurityFailed(self, data): + print "Security failed cause to %s"%data.getvalue() + + def readServerInit(self, data): + ''' + read server init packet + ''' + self._width = data.read_beuint16() + self._height = data.read_beuint16() + serverPixelFomat = PixelFormat() + serverPixelFomat.read(data) + self.expectWithHeader(4, self.readServerName) + + def readServerName(self, data): + ''' + read server name from server init packet + ''' + self._serverName = data.getvalue() + print "Server name %s"%self._serverName + #end of handshake + #send pixel format + self.writeSetPixelFormat(self._pixelFormat) + #write encoding + self.writeSetEncoding() + #request entire zone + self.writeFramebufferUpdateRequest(False, 0, 0, self._width, self._height) + self.expect(1, self.readServerOrder) + + def readServerOrder(self, data): + ''' + read order receive from server + ''' + packet_type = data.read_uint8() + if packet_type == 0: + self.expect(3, self.readFrameBufferUpdateHeader) + + def readFrameBufferUpdateHeader(self, data): + ''' + read frame buffer update packet header + ''' + #padding + data.read_uint8() + self._nbRect = data.read_beuint16(); + self.expect(12, self.readRectHeader) + + def readRectHeader(self, data): + ''' + read rectangle header + ''' + self._currentRect.X = data.read_beuint16() + self._currentRect.Y = data.read_beuint16() + self._currentRect.Width = data.read_beuint16() + self._currentRect.Height = data.read_beuint16() + self._currentRect.Encoding = data.read_besint32() + + if self._currentRect.Encoding == Encoding.RAW: + self.expect(self._currentRect.Width * self._currentRect.Height * (self._pixelFormat.BitsPerPixel / 8), self.readRectBody) + + def readRectBody(self, data): + ''' + read body of rect + ''' + for observer in self._observer: + observer.notifyFramebufferUpdate(self._currentRect.Width, self._currentRect.Height, self._currentRect.X, self._currentRect.Y, self._pixelFormat, self._currentRect.Encoding, data.getvalue()) + self._nbRect = self._nbRect - 1 + #if there is another rect to read + if self._nbRect == 0: + #job is finish send a request + self.writeFramebufferUpdateRequest(True, 0, 0, self._width, self._height) + self.expect(1, self.readServerOrder) + else: + self.expect(12, self.readRectHeader) + + def writeClientInit(self): + ''' + write client init packet + ''' + s = Stream() + s.write_uint8(self._sharedFlag) + self.transport.write(s.getvalue()) + self.expect(20, self.readServerInit) + + def writeSetPixelFormat(self, pixelFormat): + ''' + write set pixel format packet + ''' + s = Stream() + #message type + s.write_uint8(0) + #padding + s.write_uint8(0) + s.write_uint8(0) + s.write_uint8(0) + pixelFormat.write(s) + self.transport.write(s.getvalue()) + + def writeSetEncoding(self): + ''' + write set encoding packet + ''' + s = Stream() + #message type + s.write_uint8(2) + #padding + s.write_uint8(0) + #nb encoding + s.write_beuint16(1) + #raw encoding + s.write_besint32(0) + self.transport.write(s.getvalue()) + + def writeFramebufferUpdateRequest(self, incremental, x, y, width, height): + ''' + request server the specified zone + incremental means request only change before last update + ''' + s = Stream() + s.write_uint8(3) + s.write_uint8(incremental) + s.write_beuint16(x) + s.write_beuint16(y) + s.write_beuint16(width) + s.write_beuint16(height) + self.transport.write(s.getvalue()) + + def writeKeyEvent(self, downFlag, key): + ''' + write key event packet + ''' + s = Stream() + s.write_uint8(4) + s.write_uint8(downFlag) + s.write_beuint16(0) + s.write_beuint32(key) + self.transport.write(s.getvalue()) + + def writePointerEvent(self, mask, x, y): + ''' + write pointer event packet + ''' + s= Stream() + s.write_uint8(5) + s.write_uint8(mask) + s.write_beuint16(x) + s.write_beuint16(y) + self.transport.write(s.getvalue()) + + def writeClientCutText(self, text): + ''' + write client cut text event packet + ''' + s = Stream() + s.write_uint8(6) + #padding + s.write_uint8(0) + s.write_uint8(0) + s.write_uint8(0) + s.write_beuint32(len(text)) + s.write(text) + self.transport.write(s.getvalue()) \ No newline at end of file diff --git a/rdpy/protocols/rfb/rfb.pyc b/rdpy/protocols/rfb/rfb.pyc new file mode 100644 index 0000000..77d8d5a Binary files /dev/null and b/rdpy/protocols/rfb/rfb.pyc differ diff --git a/rdpy/protocols/rfb/types.py b/rdpy/protocols/rfb/types.py new file mode 100644 index 0000000..04322e6 --- /dev/null +++ b/rdpy/protocols/rfb/types.py @@ -0,0 +1,80 @@ +''' +Created on 22 aout 2013 + +@author: sylvain +''' +class ProtocolVersion(object): + ''' + different ptotocol version + ''' + UNKNOWN = 0 + RFB003003 = 1 + RFB003007 = 2 + RFB003008 = 3 + +class SecurityType: + ''' + security type supported by twisted remote desktop + ''' + INVALID = 0 + NONE = 1 + VNC = 2 + +class PixelFormat(object): + def __init__(self): + self.BitsPerPixel = 32 + self.Depth = 24 + self.BigEndianFlag = False + self.TrueColorFlag = True + self.RedMax = 255 + self.GreenMax = 255 + self.BlueMax = 255 + self.RedShift = 16 + self.GreenShift = 8 + self.BlueShift = 0 + + def read(self, data): + self.BitsPerPixel = data.read_uint8() + self.Depth = data.read_uint8() + self.BigEndianFlag = data.read_uint8() + self.TrueColorFlag = data.read_uint8() + self.RedMax = data.read_beuint16() + self.GreenMax = data.read_beuint16() + self.BlueMax = data.read_beuint16() + self.RedShift = data.read_uint8() + self.GreenShift = data.read_uint8() + self.BlueShift = data.read_uint8() + #padding + data.read(3) + + def write(self, data): + data.write_uint8(self.BitsPerPixel) + data.write_uint8(self.Depth) + data.write_uint8(self.BigEndianFlag) + data.write_uint8(self.TrueColorFlag) + data.write_beuint16(self.RedMax) + data.write_beuint16(self.GreenMax) + data.write_beuint16(self.BlueMax) + data.write_uint8(self.RedShift) + data.write_uint8(self.GreenShift) + data.write_uint8(self.BlueShift) + #padding + data.write_uint8(0) + data.write_uint8(0) + data.write_uint8(0) + +class Pointer: + BUTTON1 = 0x1 + BUTTON2 = 0x2 + BUTTON3 = 0x4 + +class Rectangle: + def __init__(self): + self.X = 0 + self.Y = 0 + self.Width = 0 + self.Height = 0 + self.Encoding = 0 + +class Encoding: + RAW = 0 \ No newline at end of file diff --git a/rdpy/protocols/rfb/types.pyc b/rdpy/protocols/rfb/types.pyc new file mode 100644 index 0000000..4054b1e Binary files /dev/null and b/rdpy/protocols/rfb/types.pyc differ diff --git a/rdpy/qt/__init__.py b/rdpy/qt/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/rdpy/qt/__init__.pyc b/rdpy/qt/__init__.pyc new file mode 100644 index 0000000..65985a2 Binary files /dev/null and b/rdpy/qt/__init__.pyc differ diff --git a/rdpy/qt/adaptor.py b/rdpy/qt/adaptor.py new file mode 100644 index 0000000..e4952a8 --- /dev/null +++ b/rdpy/qt/adaptor.py @@ -0,0 +1,63 @@ +''' +Created on 4 sept. 2013 +@author: sylvain +''' +from PyQt4 import QtGui +from rdpy.protocols.rfb.observer import RfbObserver + +class QAdaptor(object): + ''' + Adaptor for all qt + ''' + def __init__(self): + self._observers = [] + + def addObserver(self, observer): + self._observers.append(observer) + + def notifyImage(self, x, y, qimage): + for observer in self._observers: + observer.notifyImage(x, y, qimage) + + def sendMouseEvent(self, e): + pass + def sendKeyEvent(self, e): + pass + + +class RfbAdaptor(RfbObserver, QAdaptor): + ''' + classdocs + ''' + + def __init__(self, rfb): + QAdaptor.__init__(self) + self._rfb = rfb + self._rfb.addObserver(self) + + def notifyFramebufferUpdate(self, width, height, x, y, pixelFormat, encoding, data): + ''' + implement RfbAdaptor interface + ''' + + imageFormat = None + if pixelFormat.BitsPerPixel == 32 and pixelFormat.RedShift == 16: + imageFormat = QtGui.QImage.Format_RGB32 + else: + print "Receive image in bad format" + return + + image = QtGui.QImage(data, width, height, imageFormat) + self.notifyImage(x, y, image) + + def sendMouseEvent(self, e): + ''' + convert qt mouse event to rfb mouse event + ''' + self._rfb.writePointerEvent(0, e.pos().x(), e.pos().y()) + + def sendKeyEvent(self, e): + ''' + convert qt key press event to rfb press event + ''' + self._rfb.writeKeyEvent(True, e.nativeVirtualKey()) \ No newline at end of file diff --git a/rdpy/qt/adaptor.pyc b/rdpy/qt/adaptor.pyc new file mode 100644 index 0000000..3b105d4 Binary files /dev/null and b/rdpy/qt/adaptor.pyc differ diff --git a/rdpy/qt/observer.py b/rdpy/qt/observer.py new file mode 100644 index 0000000..0428bf2 --- /dev/null +++ b/rdpy/qt/observer.py @@ -0,0 +1,12 @@ +''' +Created on 4 sept. 2013 + +@author: sylvain +''' + +class QObserver(object): + ''' + classdocs + ''' + def notifyImage(self, x, y, qimage): + pass \ No newline at end of file diff --git a/rdpy/qt/observer.pyc b/rdpy/qt/observer.pyc new file mode 100644 index 0000000..a28e1cd Binary files /dev/null and b/rdpy/qt/observer.pyc differ diff --git a/rdpy/qt/widget.py b/rdpy/qt/widget.py new file mode 100644 index 0000000..f8f6cf7 --- /dev/null +++ b/rdpy/qt/widget.py @@ -0,0 +1,38 @@ +''' +Created on 4 sept. 2013 + +@author: sylvain +''' + +from PyQt4 import QtGui +from observer import QObserver + +class QRemoteDesktop(QtGui.QWidget, QObserver): + + def __init__(self, adaptor): + super(QRemoteDesktop, self).__init__() + self._adaptor = adaptor + self._adaptor.addObserver(self) + self._refresh = [] + self.setMouseTracking(True) + + def notifyImage(self, x, y, qimage): + self._refresh.append({"x" : x, "y" : y, "image" : qimage}) + self.update() + + def paintEvent(self, e): + if self._refresh == []: + return + qp = QtGui.QPainter() + qp.begin(self) + for image in self._refresh: + qp.drawImage(image["x"], image["y"], image["image"]) + qp.end() + + self._lastReceive = [] + + def mouseMoveEvent(self, event): + self._adaptor.sendMouseEvent(event) + + def keyPressEvent(self, event): + self._adaptor.sendKeyEvent(event) \ No newline at end of file diff --git a/rdpy/qt/widget.pyc b/rdpy/qt/widget.pyc new file mode 100644 index 0000000..4f38082 Binary files /dev/null and b/rdpy/qt/widget.pyc differ