From 763ed2e3ee9306cc12a40b8aa6d602c1c720afc6 Mon Sep 17 00:00:00 2001 From: speyrefitte Date: Wed, 20 May 2015 17:51:43 +0200 Subject: [PATCH] fix major bug on update handle --- bin/rdpy-rdpclient.py | 4 +-- rdpy/core/type.py | 2 +- rdpy/protocol/rdp/pdu/data.py | 64 ++++++++++++++++++---------------- rdpy/protocol/rdp/pdu/layer.py | 35 ++++++++++--------- rdpy/ui/qt4.py | 5 ++- 5 files changed, 60 insertions(+), 50 deletions(-) diff --git a/bin/rdpy-rdpclient.py b/bin/rdpy-rdpclient.py index 937b968..660bfa4 100755 --- a/bin/rdpy-rdpclient.py +++ b/bin/rdpy-rdpclient.py @@ -172,7 +172,7 @@ class RDPClientQtFactory(rdp.ClientFactory): connector.connect() return - QtGui.QMessageBox.warning(self._w, "Warning", "Lost connection : %s"%reason) + log.info("Lost connection : %s"%reason) reactor.stop() app.exit() @@ -182,7 +182,7 @@ class RDPClientQtFactory(rdp.ClientFactory): @param connector: twisted connector use for rdp connection (use reconnect to restart connection) @param reason: str use to advertise reason of lost connection """ - QtGui.QMessageBox.warning(self._w, "Warning", "Connection failed : %s"%reason) + log.info("Connection failed : %s"%reason) reactor.stop() app.exit() diff --git a/rdpy/core/type.py b/rdpy/core/type.py index 804ca5d..260c672 100644 --- a/rdpy/core/type.py +++ b/rdpy/core/type.py @@ -477,7 +477,7 @@ class CompositeType(Type): raise e if not self._readLen is None and readLen < self._readLen.value: - log.debug("Still have correct data in packet %s, read it as padding"%self.__class__) + log.debug("Still have correct data in packet %s, read %s bytes as padding"%(self.__class__, self._readLen.value - readLen)) s.read(self._readLen.value - readLen) def __write__(self, s): diff --git a/rdpy/protocol/rdp/pdu/data.py b/rdpy/protocol/rdp/pdu/data.py index 84a19b8..e7caf36 100644 --- a/rdpy/protocol/rdp/pdu/data.py +++ b/rdpy/protocol/rdp/pdu/data.py @@ -413,8 +413,6 @@ class ErrorInfo(object): ERRINFO_VCDATATOOLONG : "The size of a received Virtual Channel PDU (section 2.2.6.1) exceeds the chunking size specified in the Virtual Channel Capability Set (section 2.2.7.1.10).", } - - class ShareControlHeader(CompositeType): """ @summary: PDU share control header @@ -461,10 +459,10 @@ class PDU(CompositeType): """ for c in [DemandActivePDU, ConfirmActivePDU, DataPDU, DeactiveAllPDU]: if self.shareControlHeader.pduType.value == c._PDUTYPE_: - return c() + return c(readLen = CallableValue(self.shareControlHeader.totalLength.value - sizeof(self.shareControlHeader))) log.debug("unknown PDU type : %s"%hex(self.shareControlHeader.pduType.value)) #read entire packet - return String() + return String(readLen = CallableValue(self.shareControlHeader.totalLength.value - sizeof(self.shareControlHeader))) if pduMessage is None: pduMessage = FactoryType(PDUMessageFactory) @@ -481,8 +479,8 @@ class DemandActivePDU(CompositeType): #may declare the PDU type _PDUTYPE_ = PDUType.PDUTYPE_DEMANDACTIVEPDU - def __init__(self): - CompositeType.__init__(self) + def __init__(self, readLen = None): + CompositeType.__init__(self, readLen = readLen) self.shareId = UInt32Le() self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor)) self.lengthCombinedCapabilities = UInt16Le(lambda:(sizeof(self.numberCapabilities) + sizeof(self.pad2Octets) + sizeof(self.capabilitySets))) @@ -500,8 +498,8 @@ class ConfirmActivePDU(CompositeType): #may declare the PDU type _PDUTYPE_ = PDUType.PDUTYPE_CONFIRMACTIVEPDU - def __init__(self): - CompositeType.__init__(self) + def __init__(self, readLen = None): + CompositeType.__init__(self, readLen = readLen) self.shareId = UInt32Le() self.originatorId = UInt16Le(0x03EA, constant = True) self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor)) @@ -519,10 +517,10 @@ class DeactiveAllPDU(CompositeType): #may declare the PDU type _PDUTYPE_ = PDUType.PDUTYPE_DEACTIVATEALLPDU - def __init__(self): + def __init__(self, readLen = None): #in old version this packet is empty i don't know #and not specified - CompositeType.__init__(self, optional = True) + CompositeType.__init__(self, optional = True, readLen = readLen) self.shareId = UInt32Le() self.lengthSourceDescriptor = UInt16Le(lambda:sizeof(self.sourceDescriptor)) self.sourceDescriptor = String("rdpy", readLen = self.lengthSourceDescriptor) @@ -534,8 +532,8 @@ class DataPDU(CompositeType): #may declare the PDU type _PDUTYPE_ = PDUType.PDUTYPE_DATAPDU - def __init__(self, pduData = None, shareId = 0): - CompositeType.__init__(self) + def __init__(self, pduData = None, shareId = 0, readLen = None): + CompositeType.__init__(self, readLen = readLen) self.shareDataHeader = ShareDataHeader(lambda:sizeof(self), lambda:self.pduData.__class__._PDUTYPE2_, shareId) def PDUDataFactory(): @@ -544,9 +542,9 @@ class DataPDU(CompositeType): """ for c in [UpdateDataPDU, SynchronizeDataPDU, ControlDataPDU, ErrorInfoDataPDU, FontListDataPDU, FontMapDataPDU, PersistentListPDU, ClientInputEventPDU, ShutdownDeniedPDU, ShutdownRequestPDU, SupressOutputDataPDU, SaveSessionInfoPDU]: if self.shareDataHeader.pduType2.value == c._PDUTYPE2_: - return c() + return c(readLen = CallableValue(self.shareDataHeader.uncompressedLength.value - 18)) log.debug("unknown PDU data type : %s"%hex(self.shareDataHeader.pduType2.value)) - return String() + return String(readLen = CallableValue(self.shareDataHeader.uncompressedLength.value - 18)) if pduData is None: pduData = FactoryType(PDUDataFactory) @@ -655,8 +653,8 @@ class PersistentListPDU(CompositeType): """ _PDUTYPE2_ = PDUType2.PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST - def __init__(self, userId = 0, shareId = 0): - CompositeType.__init__(self) + def __init__(self, userId = 0, shareId = 0, readLen = None): + CompositeType.__init__(self, readLen = readLen) self.numEntriesCache0 = UInt16Le() self.numEntriesCache1 = UInt16Le() self.numEntriesCache2 = UInt16Le() @@ -679,8 +677,8 @@ class ClientInputEventPDU(CompositeType): """ _PDUTYPE2_ = PDUType2.PDUTYPE2_INPUT - def __init__(self): - CompositeType.__init__(self) + def __init__(self, readLen = None): + CompositeType.__init__(self, readLen = readLen) self.numEvents = UInt16Le(lambda:len(self.slowPathInputEvents._array)) self.pad2Octets = UInt16Le() self.slowPathInputEvents = ArrayType(SlowPathInputEvent, readLen = self.numEvents) @@ -691,8 +689,8 @@ class ShutdownRequestPDU(CompositeType): client -> server """ _PDUTYPE2_ = PDUType2.PDUTYPE2_SHUTDOWN_REQUEST - def __init__(self): - CompositeType.__init__(self) + def __init__(self, readLen = None): + CompositeType.__init__(self, readLen = readLen) class ShutdownDeniedPDU(CompositeType): """ @@ -700,8 +698,8 @@ class ShutdownDeniedPDU(CompositeType): server -> client """ _PDUTYPE2_ = PDUType2.PDUTYPE2_SHUTDOWN_DENIED - def __init__(self): - CompositeType.__init__(self) + def __init__(self, readLen = None): + CompositeType.__init__(self, readLen = readLen) class InclusiveRectangle(CompositeType): """ @@ -761,9 +759,15 @@ class UpdateDataPDU(CompositeType): """ for c in [BitmapUpdateDataPDU]: if self.updateType.value == c._UPDATE_TYPE_: - return c() + if not readLen is None: + return c(readLen = CallableValue(readLen.value - 2)) + else: + return c() log.debug("unknown PDU update data type : %s"%hex(self.updateType.value)) - return String() + if not readLen is None: + return String(readLen = CallableValue(readLen.value - 2)) + else: + return String() if updateData is None: updateData = FactoryType(UpdateDataFactory, conditional = lambda:(self.updateType.value != UpdateType.UPDATETYPE_SYNCHRONIZE)) @@ -801,9 +805,9 @@ class FastPathUpdatePDU(CompositeType): """ for c in [FastPathBitmapUpdateDataPDU]: if (self.updateHeader.value & 0xf) == c._FASTPATH_UPDATE_TYPE_: - return c() + return c(readLen = self.size) log.debug("unknown Fast Path PDU update data type : %s"%hex(self.updateHeader.value & 0xf)) - return String() + return String(readLen = self.size) if updateData is None: updateData = FactoryType(UpdateDataFactory) @@ -833,8 +837,8 @@ class OrderUpdateDataPDU(CompositeType): @see: http://msdn.microsoft.com/en-us/library/cc241571.aspx @todo: not implemented yet but need it """ - def __init__(self): - CompositeType.__init__(self) + def __init__(self, readLen = None): + CompositeType.__init__(self, readLen = readLen) self.pad2OctetsA = UInt16Le() self.numberOrders = UInt16Le(lambda:len(self.orderData._array)) self.pad2OctetsB = UInt16Le() @@ -894,8 +898,8 @@ class FastPathBitmapUpdateDataPDU(CompositeType): """ _FASTPATH_UPDATE_TYPE_ = FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP - def __init__(self): - CompositeType.__init__(self) + def __init__(self, readLen = None): + CompositeType.__init__(self, readLen = readLen) self.header = UInt16Le(FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP, constant = True) self.numberRectangles = UInt16Le(lambda:len(self.rectangles._array)) self.rectangles = ArrayType(BitmapData, readLen = self.numberRectangles) diff --git a/rdpy/protocol/rdp/pdu/layer.py b/rdpy/protocol/rdp/pdu/layer.py index f326701..dcf68e9 100644 --- a/rdpy/protocol/rdp/pdu/layer.py +++ b/rdpy/protocol/rdp/pdu/layer.py @@ -25,6 +25,7 @@ In this layer are managed all mains bitmap update orders end user inputs from rdpy.core.layer import LayerAutomata from rdpy.core.error import CallPureVirtualFuntion +from rdpy.core.type import ArrayType import rdpy.core.log as log import rdpy.protocol.rdp.tpkt as tpkt import data, caps @@ -266,15 +267,16 @@ class Client(PDULayer): @summary: Main receive function after connection sequence @param s: Stream from transport layer """ - pdu = data.PDU() - s.readType(pdu) - if pdu.shareControlHeader.pduType.value == data.PDUType.PDUTYPE_DATAPDU: - self.readDataPDU(pdu.pduMessage) - elif pdu.shareControlHeader.pduType.value == data.PDUType.PDUTYPE_DEACTIVATEALLPDU: - #use in deactivation-reactivation sequence - #next state is either a capabilities re exchange or disconnection - #http://msdn.microsoft.com/en-us/library/cc240454.aspx - self.setNextState(self.recvDemandActivePDU) + pdus = ArrayType(data.PDU) + s.readType(pdus) + for pdu in pdus: + if pdu.shareControlHeader.pduType.value == data.PDUType.PDUTYPE_DATAPDU: + self.readDataPDU(pdu.pduMessage) + elif pdu.shareControlHeader.pduType.value == data.PDUType.PDUTYPE_DEACTIVATEALLPDU: + #use in deactivation-reactivation sequence + #next state is either a capabilities re exchange or disconnection + #http://msdn.microsoft.com/en-us/library/cc240454.aspx + self.setNextState(self.recvDemandActivePDU) def recvFastPath(self, secFlag, fastPathS): """ @@ -283,11 +285,12 @@ class Client(PDULayer): @param fastPathS: {Stream} that contain fast path data @param secFlag: {SecFlags} """ - fastPathPDU = data.FastPathUpdatePDU() - fastPathS.readType(fastPathPDU) - if fastPathPDU.updateHeader.value == data.FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP: - self._listener.onUpdate(fastPathPDU.updateData.rectangles._array) - + updates = ArrayType(data.FastPathUpdatePDU) + fastPathS.readType(updates) + for update in updates: + if update.updateHeader.value == data.FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP: + self._listener.onUpdate(update.updateData.rectangles._array) + def readDataPDU(self, dataPDU): """ @summary: read a data PDU object @@ -329,8 +332,8 @@ class Client(PDULayer): generalCapability.osMajorType.value = caps.MajorType.OSMAJORTYPE_WINDOWS generalCapability.osMinorType.value = caps.MinorType.OSMINORTYPE_WINDOWS_NT generalCapability.extraFlags.value = caps.GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED | caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR | caps.GeneralExtraFlag.ENC_SALTED_CHECKSUM - if not self._fastPathSender is None: - generalCapability.extraFlags.value |= caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED + #if not self._fastPathSender is None: + # generalCapability.extraFlags.value |= caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED #init bitmap capability bitmapCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_BITMAP].capability diff --git a/rdpy/ui/qt4.py b/rdpy/ui/qt4.py index 5f17155..63a3b14 100644 --- a/rdpy/ui/qt4.py +++ b/rdpy/ui/qt4.py @@ -241,6 +241,7 @@ class RDPClientQt(RDPClientObserver, QAdaptor): self._widget = QRemoteDesktop(width, height, self) #set widget screen to RDP stack controller.setScreen(width, height) + self._i = 0 def getWidget(self): """ @@ -303,7 +304,9 @@ class RDPClientQt(RDPClientObserver, QAdaptor): @param isCompress: {bool} use RLE compression @param data: {str} bitmap data """ - image = RDPBitmapToQtImage(width, height, bitsPerPixel, isCompress, data); + image = RDPBitmapToQtImage(width, height, bitsPerPixel, isCompress, data) + image.save("/tmp/%s.png"%self._i) + self._i += 1 #if image need to be cut #For bit alignement server may send more than image pixel self._widget.notifyImage(destLeft, destTop, image, destRight - destLeft + 1, destBottom - destTop + 1)