repair TPKT layer with new packet manager

This commit is contained in:
speyrefitte
2013-10-17 17:59:05 +02:00
parent 05b732c778
commit 798076ff29
9 changed files with 259 additions and 153 deletions

View File

@@ -4,7 +4,7 @@ Created on 4 sept. 2013
'''
from PyQt4 import QtGui
from rdpy.protocol.rfb.observer import RfbObserver
from rdpy.protocol.common.network import UInt8, UInt16Be
from rdpy.protocol.network.type import UInt8
class QAdaptor(object):
'''

View File

@@ -70,8 +70,7 @@ class LayerAutomata(Layer):
#twitsed layer concept
from twisted.internet import protocol
#first that handle stream
from network import Stream, Type
from error import InvalidType
from type import Stream
class RawLayer(protocol.Protocol, LayerAutomata):
'''
@@ -121,7 +120,7 @@ class RawLayer(protocol.Protocol, LayerAutomata):
#default callback is recv from LayerAutomata
self.setNextState(callback)
def sendMessage(self, message):
def send(self, message):
'''
send stream on tcp layer
'''

View File

@@ -4,7 +4,22 @@
import struct
from StringIO import StringIO
from error import InvalidValue
from error import InvalidValue, InvalidType
def sizeof(element):
'''
byte size of type
'''
if isinstance(element, tuple):
size = 0
for i in element:
size += sizeof(i)
return size
elif isinstance(element, Type):
return element.__sizeof__()
raise InvalidType("invalid type for sizeof")
class Type(object):
'''
@@ -22,7 +37,7 @@ class Type(object):
'''
pass
def sizeof(self):
def __sizeof__(self):
'''
return size of type
'''
@@ -35,7 +50,7 @@ class SimpleType(Type):
def __init__(self, structFormat, typeSize, value):
self._typeSize = typeSize
self._structFormat = structFormat
self._value = value
self.value = value
@property
def value(self):
@@ -44,6 +59,15 @@ class SimpleType(Type):
'''
return self._value
@value.setter
def value(self, value):
'''
setter of value after check it
'''
if self.__class__.__dict__.has_key("isInRange") and not self.__class__.isInRange(value):
raise InvalidValue("value is out of range for %s"%self.__class__)
self._value = value
def __cmp__(self, other):
'''
compare inner value
@@ -62,7 +86,7 @@ class SimpleType(Type):
'''
self._value = struct.unpack(self._structFormat,s.read(self._typeSize))[0]
def sizeof(self):
def __sizeof__(self):
'''
return size of type
'''
@@ -101,26 +125,33 @@ class CompositeType(Type):
for i in self._type:
s.writeType(i)
def sizeof(self):
def __sizeof__(self):
'''
call sizeof on each subtype
'''
result = 0
size = 0
for i in self._type:
result += i.sizeof()
size += sizeof(i)
return size
class UInt8(SimpleType):
'''
unsigned byte
'''
'''
def __init__(self, value = 0):
'''
constructor check value range
'''
if value < 0 or value > 0xff:
raise InvalidValue("invalid UInt8 value")
SimpleType.__init__(self, "B", 1, value)
@staticmethod
def isInRange(value):
'''
return true if value is in UInt8 range
'''
return not (value < 0 or value > 0xff)
class UInt16Be(SimpleType):
'''
unsigned short with big endian representation
@@ -129,10 +160,15 @@ class UInt16Be(SimpleType):
'''
constructor check value range
'''
if value < 0 or value > 0xffff:
raise InvalidValue("invalid UInt16Be value")
SimpleType.__init__(self, ">H", 2, value)
@staticmethod
def isInRange(value):
'''
return true if value is in UInt8 range
'''
return not (value < 0 or value > 0xffff)
class UInt16Le(SimpleType):
'''
unsigned short with little endian representation
@@ -141,10 +177,15 @@ class UInt16Le(SimpleType):
'''
constructor check value range
'''
if value < 0 or value > 0xffff:
raise InvalidValue("invalid UInt16Le value")
SimpleType.__init__(self, "<H", 2, value)
@staticmethod
def isInRange(value):
'''
return true if value is in UInt8 range
'''
return not (value < 0 or value > 0xffff)
class UInt32Be(SimpleType):
'''
unsigned int with big endian representation
@@ -153,10 +194,15 @@ class UInt32Be(SimpleType):
'''
constructor check value range
'''
if value < 0 or value > 0xffffffff:
raise InvalidValue("invalid UInt32Be value")
SimpleType.__init__(self, ">I", 4, value)
@staticmethod
def isInRange(value):
'''
return true if value is in UInt8 range
'''
return not (value < 0 or value > 0xffffffff)
class UInt32Le(SimpleType):
'''
unsigned int with little endian representation
@@ -165,9 +211,14 @@ class UInt32Le(SimpleType):
'''
constructor check value range
'''
if value < 0 or value > 0xffffffff:
raise InvalidValue("invalid UInt32Le value")
SimpleType.__init__(self, "<I", 4, value)
@staticmethod
def isInRange(value):
'''
return true if value is in UInt8 range
'''
return not (value < 0 or value > 0xffffffff)
class SInt32Le(SimpleType):
'''
@@ -177,10 +228,15 @@ class SInt32Le(SimpleType):
'''
constructor check value range
'''
if value < ~0x7fffffff or value > 0x7fffffff:
raise InvalidValue("invalid UInt32Le value")
SimpleType.__init__(self, "<I", 4, value)
@staticmethod
def isInRange(value):
'''
return true if value is in UInt8 range
'''
return not (value < ~0x7fffffff or value > 0x7fffffff)
class SInt32Be(SimpleType):
'''
unsigned int with big endian representation
@@ -189,9 +245,14 @@ class SInt32Be(SimpleType):
'''
constructor check value range
'''
if value < ~0x7fffffff or value > 0x7fffffff:
raise InvalidValue("invalid UInt32Be value")
SimpleType.__init__(self, ">I", 4, value)
@staticmethod
def isInRange(value):
'''
return true if value is in UInt8 range
'''
return not (value < ~0x7fffffff or value > 0x7fffffff)
class UInt24Be(SimpleType):
'''
@@ -201,10 +262,15 @@ class UInt24Be(SimpleType):
'''
constructor check value range
'''
if value < 0 or value > 0xffffff:
raise InvalidValue("invalid UInt24Be value")
SimpleType.__init__(self, ">I", 3, value)
@staticmethod
def isInRange(value):
'''
return true if value is in UInt8 range
'''
return not (value < 0 or value > 0xffffff)
def write(self, s):
'''
special write for a special type
@@ -225,10 +291,15 @@ class UInt24Le(SimpleType):
'''
constructor check value range
'''
if value < 0 or value > 0xffffff:
raise InvalidValue("invalid UInt24Le value")
SimpleType.__init__(self, "<I", 3, value)
@staticmethod
def isInRange(value):
'''
return true if value is in UInt8 range
'''
return not (value < 0 or value > 0xffffff)
def write(self, s):
'''
special write for a special type
@@ -275,7 +346,7 @@ class String(Type):
'''
self._value = s.getvalue()
def sizeof(self):
def __sizeof__(self):
'''
return len of string
'''
@@ -308,7 +379,7 @@ class Stream(StringIO):
read next type but didn't consume it
'''
self.readType(t)
self.pos -= t.sizeof()
self.pos -= sizeof(t)
def writeType(self, value):
'''

View File

@@ -1,29 +1,68 @@
'''
@author: sylvain
'''
from rdpy.protocol.common.layer import LayerAutomata
from rdpy.protocol.common.network import Stream
from rdpy.protocol.common.error import InvalidExpectedDataException, NegotiationFailure
from rdpy.protocol.network.layer import LayerAutomata
from rdpy.protocol.network.type import UInt8, UInt16Le, UInt16Be, UInt32Le, CompositeType, sizeof
from rdpy.protocol.network.error import InvalidExpectedDataException, NegotiationFailure
from rdpy.utils.const import ConstAttributes
@ConstAttributes
class MessageType(object):
'''
message type
'''
X224_TPDU_CONNECTION_REQUEST = UInt8(0xE0)
X224_TPDU_CONNECTION_CONFIRM = UInt8(0xD0)
X224_TPDU_DISCONNECT_REQUEST = UInt8(0x80)
X224_TPDU_DATA = UInt8(0xF0)
X224_TPDU_ERROR = UInt8(0x70)
@ConstAttributes
class NegociationType(object):
'''
negotiation header
'''
TYPE_RDP_NEG_REQ = UInt8(0x01)
TYPE_RDP_NEG_RSP = UInt8(0x02)
TYPE_RDP_NEG_FAILURE = UInt8(0x03)
@ConstAttributes
class Protocols(object):
'''
protocols available for TPDU layer
'''
PROTOCOL_RDP = UInt32Le(0x00000000)
PROTOCOL_SSL = UInt32Le(0x00000001)
PROTOCOL_HYBRID = UInt32Le(0x00000002)
PROTOCOL_HYBRID_EX = UInt32Le(0x00000008)
class TPDUConnectHeader(CompositeType):
'''
header of TPDU connection messages
'''
def __init__(self, code = MessageType.X224_TPDU_CONNECTION_REQUEST, messageSize = 0):
CompositeType.__init__(self)
self.len = UInt8(messageSize + 6)
self.code = code
self.padding = (UInt16Be(), UInt16Be(), UInt8())
class NegotiationRequest(CompositeType):
'''
negociation request message
'''
def __init__(self, protocol = Protocols.PROTOCOL_SSL):
CompositeType.__init__(self)
self.header = NegociationType.TYPE_RDP_NEG_REQ
self.padding = UInt8()
#always 8
self.len = UInt16Le(0x0008)
self.protocol = protocol
class TPDU(LayerAutomata):
'''
classdocs
'''
X224_TPDU_CONNECTION_REQUEST = 0xE0
X224_TPDU_CONNECTION_CONFIRM = 0xD0
X224_TPDU_DISCONNECT_REQUEST = 0x80
X224_TPDU_DATA = 0xF0
X224_TPDU_ERROR = 0x70
#negotiation header
TYPE_RDP_NEG_REQ = 0x01
TYPE_RDP_NEG_RSP = 0x02
TYPE_RDP_NEG_FAILURE = 0x03
#rdp negotiation protocol
PROTOCOL_RDP = 0x00000000
PROTOCOL_SSL = 0x00000001
PROTOCOL_HYBRID = 0x00000002
PROTOCOL_HYBRID_EX = 0x00000008
def __init__(self, presentation = None):
'''
@@ -33,7 +72,7 @@ class TPDU(LayerAutomata):
#default protocol is SSl because is the only supported
#in this version of RDPY
self._protocol = TPDU.PROTOCOL_SSL
self._protocol = Protocols.PROTOCOL_SSL
def connect(self):
'''
@@ -41,22 +80,15 @@ class TPDU(LayerAutomata):
for client send a connection request packet
'''
self.sendConnectionRequest()
def readHeader(self, data):
'''
read a typical TPDU header (len and code)
'''
return data.read_uint8(), data.read_uint8()
def recvConnectionConfirm(self, data):
'''
recv connection confirm message
'''
(len, code) = self.readHeader(data)
if code != TPDU.X224_TPDU_CONNECTION_CONFIRM:
raise InvalidExpectedDataException("invalid TPDU header code X224_TPDU_CONNECTION_CONFIRM != %d"%code)
data.read_leuint32()
data.read_uint8()
header = TPDUConnectHeader()
data.readType(header)
if header.code != MessageType.X224_TPDU_CONNECTION_CONFIRM:
raise InvalidExpectedDataException("invalid TPDU header code X224_TPDU_CONNECTION_CONFIRM != %d"%header.code)
#check presence of negotiation response
if data.dataLen() == 8:
self.readNeg(data)
@@ -65,9 +97,8 @@ class TPDU(LayerAutomata):
'''
write connection request message
'''
s = Stream()
self.writeNegReq(s)
self.sendMessage(TPDU.X224_TPDU_CONNECTION_REQUEST, s)
neqReq = NegotiationRequest(self._protocol)
self._transport.send((TPDUConnectHeader(MessageType.X224_TPDU_CONNECTION_REQUEST, sizeof(neqReq)), neqReq))
self.setNextState(self.recvConnectionConfirm)
def send(self, data):
@@ -82,33 +113,6 @@ class TPDU(LayerAutomata):
s.write(data.getvalue())
self._transport.send(data)
def sendMessage(self, code, data = Stream()):
'''
special write function
that packet TPDU message
'''
s = Stream()
s.write_uint8(6 + data.len)
s.write_uint8(code)
s.write_beuint16(0)
s.write_beuint16(0)
s.write_uint8(0)
if data.len > 0:
s.write(data.getvalue())
self._transport.send(s)
def writeNegReq(self, s):
'''
write negociation request structure
'''
s.write_uint8(TPDU.TYPE_RDP_NEG_REQ)
#flags
s.write_uint8(0)
#write fixed packet size
s.write_leuint16(0x0008)
#write protocol
s.write_leuint32(self._protocol)
def readNeg(self, data):
'''
read neagotiation response

View File

@@ -1,8 +1,8 @@
'''
@author: sylvain
'''
from rdpy.protocol.common.layer import RawLayer
from rdpy.protocol.common.network import Stream
from rdpy.protocol.network.layer import RawLayer
from rdpy.protocol.network.type import UInt8, UInt16Be, sizeof
class TPKT(RawLayer):
'''
@@ -10,15 +10,18 @@ class TPKT(RawLayer):
this layer only handle size of packet
and determine if is a fast path packet
'''
#first byte of classic tpkt header
TPKT_PACKET = UInt8(3)
def __init__(self, presentation = None):
'''
Constructor
'''
RawLayer.__init__(self, presentation)
#last packet version read from header
self._lastPacketVersion = 0
self._lastPacketVersion = UInt8()
#length may be coded on more than 1 bytes
self._lastShortLength = 0
self._lastShortLength = UInt8()
def connect(self):
'''
@@ -36,20 +39,21 @@ class TPKT(RawLayer):
read header of TPKT packet
'''
#first read packet version
self._lastPacketVersion = data.read_uint8()
data.readType(self._lastPacketVersion)
#classic packet
if self._lastPacketVersion == 3:
data.read_uint8()
if self._lastPacketVersion == TPKT.TPKT_PACKET:
#padding
data.readType(UInt8())
#read end header
self.expect(2, self.readExtendedHeader)
else:
#is fast path packet
self._lastShortLength = data.read_uint8()
if self._lastShortLength & 0x80:
data.readType(self._lastShortLength)
if self._lastShortLength.value & 0x80:
#size is 1 byte more
self.expect(1, self.readExtendedFastPathHeader)
return
self.expect(self._lastShortLength - 2, self.readFastPath)
self.expect(self._lastShortLength.value - 2, self.readFastPath)
def readExtendedHeader(self, data):
@@ -57,16 +61,20 @@ class TPKT(RawLayer):
header may be on 4 bytes
'''
#next state is read data
self.expect(data.read_beuint16() - 4, self.readData)
size = UInt16Be()
data.readType(size)
self.expect(size.value - 4, self.readData)
def readExtendedFastPathHeader(self, data):
'''
fast ath header may be on 1 byte more
'''
self._lastShortLength &= ~0x80
self._lastShortLength = (self._lastShortLength << 8) + data.read_uint8()
leftPart = UInt8()
data.readType(leftPart)
self._lastShortLength.value &= ~0x80
self._lastShortLength.value = (self._lastShortLength.value << 8) + leftPart.value
#next state is fast patn data
self.expect(self._lastShortLength - 3, self.readFastPath)
self.expect(self._lastShortLength.value - 3, self.readFastPath)
def readFastPath(self, data):
'''
@@ -82,10 +90,8 @@ class TPKT(RawLayer):
self._presentation.recv(data)
self.expect(2, self.readHeader)
def send(self, data):
s = Stream()
s.write_uint8(3)
s.write_uint8(0)
s.write_beuint16(data.len + 4)
s.write(data.getvalue())
self.transport.write(s.getvalue())
def send(self, message):
'''
send encapsuled data
'''
RawLayer.send(self, (TPKT.TPKT_PACKET, UInt8(0), UInt16Be(sizeof(message) + 4), message))

View File

@@ -2,8 +2,7 @@
@author: sylvain
'''
from rdpy.protocol.common.network import UInt8, UInt16Be, UInt32Be, SInt32Be, String
from rdpy.protocol.common.network import CompositeType
from rdpy.protocol.network.type import UInt8, UInt16Be, UInt32Be, SInt32Be, String, CompositeType
from rdpy.utils.const import ConstAttributes
@ConstAttributes
@@ -44,6 +43,18 @@ class Encoding(object):
encoding types
'''
RAW = SInt32Be(0)
@ConstAttributes
class ClientToServerMessages(object):
'''
messages types
'''
PIXEL_FORMAT = UInt8(0)
ENCODING = UInt8(2)
FRAME_BUFFER_UPDATE_REQUEST = UInt8(3)
KEY_EVENT = UInt8(4)
POINTER_EVENT = UInt8(5)
CUT_TEXT = UInt8(6)
class PixelFormat(CompositeType):
'''
@@ -81,7 +92,6 @@ class FrameBufferUpdateRequest(CompositeType):
'''
def __init__(self, incremental = False, x = 0, y = 0, width = 0, height = 0):
CompositeType.__init__(self)
self.type = UInt8(3)
self.incremental = UInt8(incremental)
self.x = UInt16Be(x)
self.y = UInt16Be(y)
@@ -90,10 +100,43 @@ class FrameBufferUpdateRequest(CompositeType):
class Rectangle(CompositeType):
'''
header message of update rect
'''
def __init__(self):
CompositeType.__init__(self)
self.x = UInt16Be()
self.y = UInt16Be()
self.width = UInt16Be()
self.height = UInt16Be()
self.encoding = SInt32Be()
self.encoding = SInt32Be()
class KeyEvent(CompositeType):
'''
key event structure message
'''
def __init__(self, downFlag = False, key = 0):
CompositeType.__init__(self)
self.downFlag = UInt8(downFlag)
self.padding = UInt16Be()
self.key = UInt32Be(key)
class PointerEvent(CompositeType):
'''
pointer event structure message
'''
def __init__(self, mask = 0, x = 0, y = 0):
CompositeType.__init__(self)
self.mask = UInt8(mask)
self.x = UInt16Be(x)
self.y = UInt16Be(y)
class ClientCutText(CompositeType):
'''
client cut text message message
'''
def __init__(self, text = ""):
CompositeType.__init__(self)
self.padding = (UInt16Be(), UInt8())
self.size = UInt32Be(len(text))
self.message = String(text)

View File

@@ -4,9 +4,10 @@ Created on 12 aout 2013
@author: sylvain
'''
from rdpy.protocol.common.network import Stream, String, UInt8, UInt16Be, UInt32Be
from rdpy.protocol.common.layer import RawLayer
from types import ServerInit, PixelFormat, FrameBufferUpdateRequest, ProtocolVersion, SecurityType, Rectangle, Encoding
from rdpy.protocol.network.type import String, UInt8, UInt16Be, UInt32Be
from rdpy.protocol.network.layer import RawLayer
from message import ServerInit, PixelFormat, FrameBufferUpdateRequest, Rectangle, KeyEvent, PointerEvent, ClientCutText
from message import ProtocolVersion, SecurityType, Encoding, ClientToServerMessages
class Rfb(RawLayer):
'''
@@ -33,7 +34,7 @@ class Rfb(RawLayer):
#shared framebuffer client init message
self._sharedFlag = UInt8(False)
#server init message
#that contain framebuffer dim and pixel format
#which contain framebuffer dim and pixel format
self._serverInit = ServerInit()
#client pixel format
self._pixelFormat = PixelFormat()
@@ -85,7 +86,7 @@ class Rfb(RawLayer):
if self._mode == Rfb.CLIENT:
self.expect(12, self.readProtocolVersion)
else:
self.sendMessage(self._version)
self.send(self._version)
def readProtocolVersionFormat(self, data):
'''
@@ -106,7 +107,7 @@ class Rfb(RawLayer):
#protocol version is unknow try best version we can handle
self._version = ProtocolVersion.RFB003008
#send same version of
self.sendMessage(self._version)
self.send(self._version)
#next state read security
if self._version == ProtocolVersion.RFB003003:
@@ -137,7 +138,7 @@ class Rfb(RawLayer):
self._securityLevel = s
break
#send back security level choosen
self.sendMessage(self._securityLevel)
self.send(self._securityLevel)
self.expect(4, self.readSecurityResult)
def readSecurityResult(self, data):
@@ -176,7 +177,7 @@ class Rfb(RawLayer):
#write encoding
self.sendSetEncoding()
#request entire zone
self.sendMessage(FrameBufferUpdateRequest(False, 0, 0, self._serverInit.width.value, self._serverInit.height.value))
self.sendFramebufferUpdateRequest(False, 0, 0, self._serverInit.width.value, self._serverInit.height.value)
self.expect(1, self.readServerOrder)
def readServerOrder(self, data):
@@ -184,7 +185,7 @@ class Rfb(RawLayer):
read order receive from server
'''
packet_type = UInt8()
data.readNextType(packet_type)
data.readType(packet_type)
if packet_type == UInt8(0):
self.expect(3, self.readFrameBufferUpdateHeader)
@@ -216,7 +217,7 @@ class Rfb(RawLayer):
#if there is another rect to read
if self._nbRect == 0:
#job is finish send a request
self.sendMessage(FrameBufferUpdateRequest(True, 0, 0, self._serverInit.width.value, self._serverInit.height.value))
self.sendFramebufferUpdateRequest(True, 0, 0, self._serverInit.width.value, self._serverInit.height.value)
self.expect(1, self.readServerOrder)
else:
self.expect(12, self.readRectHeader)
@@ -225,60 +226,42 @@ class Rfb(RawLayer):
'''
write client init packet
'''
self.sendMessage(self._sharedFlag)
self.send(self._sharedFlag)
self.expect(20, self.readServerInit)
def sendPixelFormat(self, pixelFormat):
'''
send pixel format structure
'''
self.sendMessage((UInt8(0), UInt16Be(), UInt8(), pixelFormat))
self.send((ClientToServerMessages.PIXEL_FORMAT, UInt16Be(), UInt8(), pixelFormat))
def sendSetEncoding(self):
'''
send set encoding packet
'''
self.sendMessage((UInt8(2), UInt8(), UInt16Be(1), Encoding.RAW))
self.send((ClientToServerMessages.ENCODING, UInt8(), UInt16Be(1), Encoding.RAW))
def sendFramebufferUpdateRequest(self, incremental, x, y, width, height):
'''
request server the specified zone
incremental means request only change before last update
'''
self.sendMessage(FrameBufferUpdateRequest(incremental, x, y, width, height))
self.send((ClientToServerMessages.FRAME_BUFFER_UPDATE_REQUEST, FrameBufferUpdateRequest(incremental, x, y, width, height)))
def sendKeyEvent(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())
self.send((ClientToServerMessages.KEY_EVENT, KeyEvent(downFlag, key)))
def sendPointerEvent(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())
self.send((ClientToServerMessages.POINTER_EVENT, PointerEvent(mask, x, y)))
def sendClientCutText(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())
self.send((ClientToServerMessages.CUT_TEXT, ClientCutText(text)))