bug fix + finish proxy

This commit is contained in:
speyrefitte
2014-07-24 17:48:12 +02:00
parent 4aa9d8c389
commit 6ba4f62ef4
9 changed files with 249 additions and 42 deletions

View File

@@ -138,5 +138,4 @@ if __name__ == '__main__':
from twisted.internet import reactor from twisted.internet import reactor
reactor.connectTCP(ip, int(port), RDPClientQtFactory(width, height, username, password, domain)) reactor.connectTCP(ip, int(port), RDPClientQtFactory(width, height, username, password, domain))
reactor.runReturn() reactor.runReturn()
app.exec_() app.exec_()
reactor.stop()

View File

@@ -21,8 +21,6 @@
""" """
RDP proxy recorder and spyer RDP proxy recorder and spyer
Proxy RDP protocol Proxy RDP protocol
With admin account you can watch all currently session
For special session you can record
""" """
import sys, os import sys, os
@@ -43,14 +41,6 @@ class ProxyServer(rdp.RDPServerObserver):
rdp.RDPServerObserver.__init__(self, controller) rdp.RDPServerObserver.__init__(self, controller)
self._client = None self._client = None
def onReady(self):
"""
Event use to inform state of server stack
Use to connect client
"""
width, height = self._controller.getScreen()
reactor.connectTCP("wav-glw-013", 3389, ProxyClientFactory(self, width, height))
def clientConnected(self, client): def clientConnected(self, client):
""" """
Event throw by client when it's ready Event throw by client when it's ready
@@ -58,6 +48,52 @@ class ProxyServer(rdp.RDPServerObserver):
""" """
self._client = client self._client = client
self._controller.setColorDepth(self._client._controller.getColorDepth()) self._controller.setColorDepth(self._client._controller.getColorDepth())
def onReady(self):
"""
Event use to inform state of server stack
Use to connect client
"""
width, height = self._controller.getScreen()
reactor.connectTCP("si-hyperv-002", 3389, ProxyClientFactory(self, width, height))
def onKeyEventScancode(self, code, isPressed):
"""
Event call when a keyboard event is catch in scan code format
@param code: scan code of key
@param isPressed: True if key is down
"""
#no client connected
if self._client is None:
return
self._client._controller.sendKeyEventScancode(code, isPressed)
def onKeyEventUnicode(self, code, isPressed):
"""
Event call when a keyboard event is catch in unicode format
@param code: unicode of key
@param isPressed: True if key is down
"""
#no client connected
if self._client is None:
return
self._client._controller.sendKeyEventUnicode(code, isPressed)
def onPointerEvent(self, x, y, button, isPressed):
"""
Event call on mouse event
@param x: x position
@param y: y position
@param button: 1, 2 or 3 button
@param isPressed: True if mouse button is pressed
"""
#no client connected
if self._client is None:
return
self._client._controller.sendPointerEvent(x, y, button, isPressed)
class ProxyClient(rdp.RDPClientObserver): class ProxyClient(rdp.RDPClientObserver):
""" """

View File

@@ -151,6 +151,12 @@ class RawLayer(protocol.Protocol, LayerAutomata, StreamSender):
""" """
#join two scheme #join two scheme
self.connect() self.connect()
def close(self):
"""
Close raw layer
"""
self.transport.loseConnection()
def expect(self, expectedLen, callback = None): def expect(self, expectedLen, callback = None):
""" """

View File

@@ -240,8 +240,8 @@ class ClientCoreData(CompositeType):
self.postBeta2ColorDepth = UInt16Le(ColorDepth.RNS_UD_COLOR_8BPP) self.postBeta2ColorDepth = UInt16Le(ColorDepth.RNS_UD_COLOR_8BPP)
self.clientProductId = UInt16Le(1) self.clientProductId = UInt16Le(1)
self.serialNumber = UInt32Le(0) self.serialNumber = UInt32Le(0)
self.highColorDepth = UInt16Le(HighColor.HIGH_COLOR_15BPP) self.highColorDepth = UInt16Le(HighColor.HIGH_COLOR_24BPP)
self.supportedColorDepths = UInt16Le(Support.RNS_UD_15BPP_SUPPORT) self.supportedColorDepths = UInt16Le(Support.RNS_UD_15BPP_SUPPORT | Support.RNS_UD_16BPP_SUPPORT | Support.RNS_UD_24BPP_SUPPORT | Support.RNS_UD_32BPP_SUPPORT)
self.earlyCapabilityFlags = UInt16Le(CapabilityFlags.RNS_UD_CS_SUPPORT_ERRINFO_PDU) self.earlyCapabilityFlags = UInt16Le(CapabilityFlags.RNS_UD_CS_SUPPORT_ERRINFO_PDU)
self.clientDigProductId = String("\x00"*64, readLen = UInt8(64)) self.clientDigProductId = String("\x00"*64, readLen = UInt8(64))
self.connectionType = UInt8() self.connectionType = UInt8()

View File

@@ -25,7 +25,7 @@ The main channel is the graphical channel.
It exist channel for file system order, audio channel, clipboard etc... It exist channel for file system order, audio channel, clipboard etc...
""" """
from rdpy.network.layer import LayerAutomata, StreamSender, Layer from rdpy.network.layer import LayerAutomata, StreamSender, Layer
from rdpy.network.type import sizeof, Stream, UInt8, UInt16Le from rdpy.network.type import sizeof, Stream, UInt8, UInt16Le, String
from rdpy.base.error import InvalidExpectedDataException, InvalidValue, InvalidSize from rdpy.base.error import InvalidExpectedDataException, InvalidValue, InvalidSize
from rdpy.protocol.rdp.ber import writeLength from rdpy.protocol.rdp.ber import writeLength
import rdpy.base.log as log import rdpy.base.log as log
@@ -137,6 +137,14 @@ class MCSLayer(LayerAutomata):
#receive opcode #receive opcode
self._receiveOpcode = receiveOpcode self._receiveOpcode = receiveOpcode
def close(self):
"""
Send disconnect provider ultimatum
"""
self._transport.send((UInt8(self.writeMCSPDUHeader(DomainMCSPDU.DISCONNECT_PROVIDER_ULTIMATUM, 1)),
per.writeEnumerates(0x80), String("\x00" * 6)))
self._transport.close()
def allChannelConnected(self): def allChannelConnected(self):
""" """
All channels are connected to MCS layer All channels are connected to MCS layer

View File

@@ -783,8 +783,8 @@ class ClientInputEventPDU(CompositeType):
class ShutdownRequestPDU(CompositeType): class ShutdownRequestPDU(CompositeType):
""" """
PDU use to signal that the session will be closzed are connected PDU use to signal that the session will be closed
server -> client client -> server
""" """
_PDUTYPE2_ = PDUType2.PDUTYPE2_SHUTDOWN_REQUEST _PDUTYPE2_ = PDUType2.PDUTYPE2_SHUTDOWN_REQUEST
def __init__(self): def __init__(self):
@@ -792,7 +792,7 @@ class ShutdownRequestPDU(CompositeType):
class ShutdownDeniedPDU(CompositeType): class ShutdownDeniedPDU(CompositeType):
""" """
PDU use to signal that the session will be closzed are connected PDU use to signal which the session will be closed is connected
server -> client server -> client
""" """
_PDUTYPE2_ = PDUType2.PDUTYPE2_SHUTDOWN_DENIED _PDUTYPE2_ = PDUType2.PDUTYPE2_SHUTDOWN_DENIED
@@ -842,17 +842,17 @@ class FastPathUpdatePDU(CompositeType):
CompositeType.__init__(self) CompositeType.__init__(self)
self.updateHeader = UInt8(lambda:updateData.__class__._FASTPATH_UPDATE_TYPE_) self.updateHeader = UInt8(lambda:updateData.__class__._FASTPATH_UPDATE_TYPE_)
self.compressionFlags = UInt8(conditional = lambda:((self.updateHeader.value >> 4) & FastPathOutputCompression.FASTPATH_OUTPUT_COMPRESSION_USED)) self.compressionFlags = UInt8(conditional = lambda:((self.updateHeader.value >> 4) & FastPathOutputCompression.FASTPATH_OUTPUT_COMPRESSION_USED))
self.size = UInt16Le() self.size = UInt16Le(lambda:sizeof(self.updateData))
def UpdateDataFactory(): def UpdateDataFactory():
""" """
Create correct object in accordance to self.updateHeader field Create correct object in accordance to self.updateHeader field
""" """
if (self.updateHeader.value & 0xf) == FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP: for c in [FastPathBitmapUpdateDataPDU]:
return (UInt16Le(FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP, constant = True), BitmapUpdateDataPDU(readLen = self.size - 2)) if (self.updateHeader.value & 0xf) == c._FASTPATH_UPDATE_TYPE_:
else: return c()
log.debug("unknown Fast Path PDU update data type : %s"%hex(self.updateHeader.value & 0xf)) log.debug("unknown Fast Path PDU update data type : %s"%hex(self.updateHeader.value & 0xf))
return String() return String()
if updateData is None: if updateData is None:
updateData = FactoryType(UpdateDataFactory) updateData = FactoryType(UpdateDataFactory)
@@ -867,7 +867,6 @@ class BitmapUpdateDataPDU(CompositeType):
@see: http://msdn.microsoft.com/en-us/library/dd306368.aspx @see: http://msdn.microsoft.com/en-us/library/dd306368.aspx
""" """
_UPDATE_TYPE_ = UpdateType.UPDATETYPE_BITMAP _UPDATE_TYPE_ = UpdateType.UPDATETYPE_BITMAP
_FASTPATH_UPDATE_TYPE_ = FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP
def __init__(self, readLen = None): def __init__(self, readLen = None):
""" """
@@ -946,7 +945,20 @@ class BitmapData(CompositeType):
self.bitmapLength = UInt16Le(lambda:(sizeof(self.bitmapComprHdr) + sizeof(self.bitmapDataStream))) self.bitmapLength = UInt16Le(lambda:(sizeof(self.bitmapComprHdr) + sizeof(self.bitmapDataStream)))
self.bitmapComprHdr = BitmapCompressedDataHeader(bodySize = lambda:sizeof(self.bitmapDataStream), scanWidth = lambda:self.width.value, uncompressedSize = lambda:(self.width.value * self.height.value * self.bitsPerPixel.value), conditional = lambda:((self.flags.value | BitmapFlag.BITMAP_COMPRESSION) and not (self.flags.value | BitmapFlag.NO_BITMAP_COMPRESSION_HDR))) self.bitmapComprHdr = BitmapCompressedDataHeader(bodySize = lambda:sizeof(self.bitmapDataStream), scanWidth = lambda:self.width.value, uncompressedSize = lambda:(self.width.value * self.height.value * self.bitsPerPixel.value), conditional = lambda:((self.flags.value | BitmapFlag.BITMAP_COMPRESSION) and not (self.flags.value | BitmapFlag.NO_BITMAP_COMPRESSION_HDR)))
self.bitmapDataStream = String(bitmapDataStream, readLen = UInt16Le(lambda:(self.bitmapLength.value if (self.flags.value | BitmapFlag.NO_BITMAP_COMPRESSION_HDR) else self.bitmapComprHdr.cbCompMainBodySize.value))) self.bitmapDataStream = String(bitmapDataStream, readLen = UInt16Le(lambda:(self.bitmapLength.value if (self.flags.value | BitmapFlag.NO_BITMAP_COMPRESSION_HDR) else self.bitmapComprHdr.cbCompMainBodySize.value)))
class FastPathBitmapUpdateDataPDU(CompositeType):
"""
Fast path version of bitmap update PDU
@see: http://msdn.microsoft.com/en-us/library/dd306368.aspx
"""
_FASTPATH_UPDATE_TYPE_ = FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP
def __init__(self):
CompositeType.__init__(self)
self.header = UInt16Le(FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP, constant = True)
self.numberRectangles = UInt16Le(lambda:len(self.rectangles._array))
self.rectangles = ArrayType(BitmapData, readLen = self.numberRectangles)
class SlowPathInputEvent(CompositeType): class SlowPathInputEvent(CompositeType):
""" """
PDU use in slow-path sending client inputs PDU use in slow-path sending client inputs

View File

@@ -64,6 +64,12 @@ class PDUServerListener(object):
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onReady", "PDUServerListener")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onReady", "PDUServerListener"))
def onSlowPathInput(self, slowPathInputEvents):
"""
Event call when slow path input are available
@param slowPathInputEvents: [data.SlowPathInputEvent]
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onSlowPathInput", "PDUServerListener"))
class PDULayer(LayerAutomata): class PDULayer(LayerAutomata):
""" """
@@ -128,6 +134,8 @@ class Client(PDULayer, tpkt.FastPathListener):
""" """
PDULayer.__init__(self) PDULayer.__init__(self)
self._listener = listener self._listener = listener
#enable or not fast path
self._fastPathSender = None
def connect(self): def connect(self):
""" """
@@ -138,12 +146,22 @@ class Client(PDULayer, tpkt.FastPathListener):
self.sendInfoPkt() self.sendInfoPkt()
#next state is license info PDU #next state is license info PDU
self.setNextState(self.recvLicenceInfo) self.setNextState(self.recvLicenceInfo)
#check if client support fast path message
self._clientFastPathSupported = False
def close(self): def close(self):
""" """
Send PDU close packet and call close method on transport method Send PDU close packet and call close method on transport method
""" """
self.sendDataPDU(data.ShutdownRequestPDU()) self._transport.close()
#self.sendDataPDU(data.ShutdownRequestPDU())
def setFastPathSender(self, fastPathSender):
"""
@param fastPathSender: tpkt.FastPathSender
@note: implement tpkt.FastPathListener
"""
self._fastPathSender = fastPathSender
def recvLicenceInfo(self, s): def recvLicenceInfo(self, s):
""" """
@@ -290,7 +308,7 @@ class Client(PDULayer, tpkt.FastPathListener):
fastPathPDU = data.FastPathUpdatePDU() fastPathPDU = data.FastPathUpdatePDU()
fastPathS.readType(fastPathPDU) fastPathS.readType(fastPathPDU)
if fastPathPDU.updateHeader.value == data.FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP: if fastPathPDU.updateHeader.value == data.FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP:
self._listener.onUpdate(fastPathPDU.updateData[1].rectangles._array) self._listener.onUpdate(fastPathPDU.updateData.rectangles._array)
def readDataPDU(self, dataPDU): def readDataPDU(self, dataPDU):
""" """
@@ -333,7 +351,9 @@ class Client(PDULayer, tpkt.FastPathListener):
generalCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability generalCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability
generalCapability.osMajorType.value = caps.MajorType.OSMAJORTYPE_WINDOWS generalCapability.osMajorType.value = caps.MajorType.OSMAJORTYPE_WINDOWS
generalCapability.osMinorType.value = caps.MinorType.OSMINORTYPE_WINDOWS_NT generalCapability.osMinorType.value = caps.MinorType.OSMINORTYPE_WINDOWS_NT
generalCapability.extraFlags.value = caps.GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED | caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR | caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED generalCapability.extraFlags.value = caps.GeneralExtraFlag.LONG_CREDENTIALS_SUPPORTED | caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR
if not self._fastPathSender is None:
generalCapability.extraFlags.value |= caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED
#init bitmap capability #init bitmap capability
bitmapCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_BITMAP].capability bitmapCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_BITMAP].capability
@@ -390,7 +410,7 @@ class Client(PDULayer, tpkt.FastPathListener):
pdu.slowPathInputEvents._array = [data.SlowPathInputEvent(x) for x in pointerEvents] pdu.slowPathInputEvents._array = [data.SlowPathInputEvent(x) for x in pointerEvents]
self.sendDataPDU(pdu) self.sendDataPDU(pdu)
class Server(PDULayer): class Server(PDULayer, tpkt.FastPathListener):
""" """
Server Automata of PDU layer Server Automata of PDU layer
""" """
@@ -400,6 +420,8 @@ class Server(PDULayer):
""" """
PDULayer.__init__(self) PDULayer.__init__(self)
self._listener = listener self._listener = listener
#fast path layer
self._fastPathSender = None
def connect(self): def connect(self):
""" """
@@ -408,6 +430,13 @@ class Server(PDULayer):
""" """
self.setNextState(self.recvInfoPkt) self.setNextState(self.recvInfoPkt)
def setFastPathSender(self, fastPathSender):
"""
@param fastPathSender: tpkt.FastPathSender
@note: implement tpkt.FastPathListener
"""
self._fastPathSender = fastPathSender
def recvInfoPkt(self, s): def recvInfoPkt(self, s):
""" """
Receive info packet from client Receive info packet from client
@@ -449,6 +478,9 @@ class Server(PDULayer):
for cap in pdu.pduMessage.capabilitySets._array: for cap in pdu.pduMessage.capabilitySets._array:
self._clientCapabilities[cap.capabilitySetType] = cap self._clientCapabilities[cap.capabilitySetType] = cap
#find use full flag
self._clientFastPathSupported = self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability.extraFlags.value & caps.GeneralExtraFlag.FASTPATH_OUTPUT_SUPPORTED
self.setNextState(self.recvClientSynchronizePDU) self.setNextState(self.recvClientSynchronizePDU)
def recvClientSynchronizePDU(self, s): def recvClientSynchronizePDU(self, s):
@@ -538,6 +570,18 @@ class Server(PDULayer):
errorMessage = data.ErrorInfo._MESSAGES_[dataPDU.pduData.errorInfo] errorMessage = data.ErrorInfo._MESSAGES_[dataPDU.pduData.errorInfo]
log.error("INFO PDU : %s"%errorMessage) log.error("INFO PDU : %s"%errorMessage)
elif dataPDU.shareDataHeader.pduType2.value == data.PDUType2.PDUTYPE2_INPUT:
self._listener.onSlowPathInput(dataPDU.pduData.slowPathInputEvents._array)
elif dataPDU.shareDataHeader.pduType2.value == data.PDUType2.PDUTYPE2_SHUTDOWN_REQUEST:
self._transport.close()
def recvFastPath(self, fastPathS):
"""
Implement FastPathListener interface
Fast path is needed by RDP 8.0
@param fastPathS: Stream that contain fast path data
"""
pass
def sendLicensingErrorMessage(self): def sendLicensingErrorMessage(self):
""" """
@@ -604,7 +648,16 @@ class Server(PDULayer):
#check bitmap header for client that want it (very old client) #check bitmap header for client that want it (very old client)
if self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability.extraFlags.value & caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR: if self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability.extraFlags.value & caps.GeneralExtraFlag.NO_BITMAP_COMPRESSION_HDR:
for bitmapData in bitmapDatas: for bitmapData in bitmapDatas:
bitmapData.flags.value |= data.BitmapFlag.NO_BITMAP_COMPRESSION_HDR if bitmapData.flags.value & data.BitmapFlag.BITMAP_COMPRESSION:
updateDataPDU = data.BitmapUpdateDataPDU() bitmapData.flags.value |= data.BitmapFlag.NO_BITMAP_COMPRESSION_HDR
updateDataPDU.rectangles._array = bitmapDatas
self.sendDataPDU(data.UpdateDataPDU(updateDataPDU)) if self._clientFastPathSupported and not self._fastPathSender is None:
#fast path case
fastPathUpdateDataPDU = data.FastPathBitmapUpdateDataPDU()
fastPathUpdateDataPDU.rectangles._array = bitmapDatas
self._fastPathSender.sendFastPath(data.FastPathUpdatePDU(fastPathUpdateDataPDU))
else:
#slow path case
updateDataPDU = data.BitmapUpdateDataPDU()
updateDataPDU.rectangles._array = bitmapDatas
self.sendDataPDU(data.UpdateDataPDU(updateDataPDU))

View File

@@ -60,6 +60,12 @@ class RDPClientController(pdu.layer.PDUClientListener):
@return: color depth set by the server (15, 16, 24) @return: color depth set by the server (15, 16, 24)
""" """
return self._pduLayer._serverCapabilities[pdu.caps.CapsType.CAPSTYPE_BITMAP].capability.preferredBitsPerPixel.value return self._pduLayer._serverCapabilities[pdu.caps.CapsType.CAPSTYPE_BITMAP].capability.preferredBitsPerPixel.value
def getKeyEventUniCodeSupport(self):
"""
@return: True if server support unicode input
"""
return self._pduLayer._serverCapabilities[pdu.caps.CapsType.CAPSTYPE_INPUT].capability.inputFlags.value & pdu.caps.InputFlags.INPUT_FLAG_UNICODE
def setPerformanceSession(self): def setPerformanceSession(self):
""" """
@@ -298,6 +304,12 @@ class RDPServerController(pdu.layer.PDUServerListener):
#restart connection sequence #restart connection sequence
self._isReady = False self._isReady = False
self._pduLayer.sendPDU(pdu.data.DeactiveAllPDU()) self._pduLayer.sendPDU(pdu.data.DeactiveAllPDU())
def setKeyEventUnicodeSupport(self):
"""
Enable key event in unicode format
"""
self._pduLayer._serverCapabilities[pdu.caps.CapsType.CAPSTYPE_INPUT].capability.inputFlags.value |= pdu.caps.InputFlags.INPUT_FLAG_UNICODE
def onReady(self): def onReady(self):
""" """
@@ -309,6 +321,31 @@ class RDPServerController(pdu.layer.PDUServerListener):
self._sendReady = True self._sendReady = True
for observer in self._serverObserver: for observer in self._serverObserver:
observer.onReady() observer.onReady()
def onSlowPathInput(self, slowPathInputEvents):
"""
Event call when slow path input are available
@param slowPathInputEvents: [data.SlowPathInputEvent]
"""
for observer in self._serverObserver:
for event in slowPathInputEvents:
#scan code
if event.messageType.value == pdu.data.InputMessageType.INPUT_EVENT_SCANCODE:
observer.onKeyEventScancode(event.slowPathInputData.keyCode.value, not (event.slowPathInputData.keyboardFlags.value & pdu.data.KeyboardFlag.KBDFLAGS_RELEASE))
#unicode
elif event.messageType.value == pdu.data.InputMessageType.INPUT_EVENT_UNICODE:
observer.onKeyEventUnicode(event.slowPathInputData.unicode.value, not (event.slowPathInputData.keyboardFlags.value & pdu.data.KeyboardFlag.KBDFLAGS_RELEASE))
#mouse event
elif event.messageType.value == pdu.data.InputMessageType.INPUT_EVENT_MOUSE:
isPressed = event.slowPathInputData.pointerFlags.value & pdu.data.PointerFlag.PTRFLAGS_DOWN
button = 0
if event.slowPathInputData.pointerFlags.value & pdu.data.PointerFlag.PTRFLAGS_BUTTON1:
button = 1
elif event.slowPathInputData.pointerFlags.value & pdu.data.PointerFlag.PTRFLAGS_BUTTON2:
button = 2
elif event.slowPathInputData.pointerFlags.value & pdu.data.PointerFlag.PTRFLAGS_BUTTON3:
button = 3
observer.onPointerEvent(event.slowPathInputData.xPos.value, event.slowPathInputData.yPos.value, button, isPressed)
def sendUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data): def sendUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
""" """
@@ -428,4 +465,30 @@ class RDPServerObserver(object):
""" """
Stack is ready and connected Stack is ready and connected
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onReady", "RDPServerObserver")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onReady", "RDPServerObserver"))
def onKeyEventScancode(self, code, isPressed):
"""
Event call when a keyboard event is catch in scan code format
@param code: scan code of key
@param isPressed: True if key is down
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onKeyEventScanCode", "RDPServerObserver"))
def onKeyEventUnicode(self, code, isPressed):
"""
Event call when a keyboard event is catch in unicode format
@param code: unicode of key
@param isPressed: True if key is down
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onKeyEventUnicode", "RDPServerObserver"))
def onPointerEvent(self, x, y, button, isPressed):
"""
Event call on mouse event
@param x: x position
@param y: y position
@param button: 1, 2 or 3 button
@param isPressed: True if mouse button is pressed
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onPointerEvent", "RDPServerObserver"))

View File

@@ -26,6 +26,14 @@ from rdpy.network.layer import RawLayer
from rdpy.network.type import UInt8, UInt16Be, sizeof from rdpy.network.type import UInt8, UInt16Be, sizeof
from rdpy.base.error import CallPureVirtualFuntion from rdpy.base.error import CallPureVirtualFuntion
class Action(object):
"""
@see: http://msdn.microsoft.com/en-us/library/cc240621.aspx
@see: http://msdn.microsoft.com/en-us/library/cc240589.aspx
"""
FASTPATH_ACTION_FASTPATH = 0x0
FASTPATH_ACTION_X224 = 0x3
class FastPathListener(object): class FastPathListener(object):
""" """
Fast path packet listener Fast path packet listener
@@ -36,19 +44,33 @@ class FastPathListener(object):
Call when fast path packet is received Call when fast path packet is received
@param fastPathS: Stream @param fastPathS: Stream
""" """
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "StreamListener")) raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recvFastPath", "recvFastPath"))
def setFastPathSender(self, fastPathSender):
"""
@param fastPathSender: FastPathSender
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "setFastPathSender", "recvFastPath"))
class TPKT(RawLayer): class FastPathSender(object):
"""
Fast path send capability
"""
def sendFastPath(self, fastPathS):
"""
@param fastPathS: type transform to stream and send as fastpath
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "sendFastPath", "FastPathSender"))
class TPKT(RawLayer, FastPathSender):
""" """
TPKT layer in RDP protocol stack TPKT layer in RDP protocol stack
This layer only handle size of packet and determine if is a fast path packet This layer only handle size of packet and determine if is a fast path packet
""" """
#first byte of classic tpkt header
TPKT_PACKET = 3
def __init__(self, presentation, fastPathListener): def __init__(self, presentation, fastPathListener):
""" """
@param presentation: presentation layer, in RDP case is TPDU layer @param presentation: presentation layer, in RDP case is TPDU layer
@param fastPathListener: FastPathListener
""" """
RawLayer.__init__(self, presentation) RawLayer.__init__(self, presentation)
#last packet version read from header #last packet version read from header
@@ -57,6 +79,8 @@ class TPKT(RawLayer):
self._lastShortLength = UInt8() self._lastShortLength = UInt8()
#fast path listener #fast path listener
self._fastPathListener = fastPathListener self._fastPathListener = fastPathListener
#set me as fast path sender
fastPathListener.setFastPathSender(self)
def connect(self): def connect(self):
""" """
@@ -77,7 +101,7 @@ class TPKT(RawLayer):
#first read packet version #first read packet version
data.readType(self._lastPacketVersion) data.readType(self._lastPacketVersion)
#classic packet #classic packet
if self._lastPacketVersion.value == TPKT.TPKT_PACKET: if self._lastPacketVersion.value == Action.FASTPATH_ACTION_X224:
#padding #padding
data.readType(UInt8()) data.readType(UInt8())
#read end header #read end header
@@ -136,4 +160,10 @@ class TPKT(RawLayer):
Send encompassed data Send encompassed data
@param message: network.Type message to send @param message: network.Type message to send
""" """
RawLayer.send(self, (UInt8(TPKT.TPKT_PACKET), UInt8(0), UInt16Be(sizeof(message) + 4), message)) RawLayer.send(self, (UInt8(Action.FASTPATH_ACTION_X224), UInt8(0), UInt16Be(sizeof(message) + 4), message))
def sendFastPath(self, fastPathS):
"""
@param fastPathS: type transform to stream and send as fastpath
"""
RawLayer.send(self, (UInt8(Action.FASTPATH_ACTION_FASTPATH), UInt16Be((sizeof(fastPathS) + 3) | 0x8000), fastPathS))