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

@@ -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))